├── .gitignore ├── Assets ├── Java Server Side Programming - The Conceptual Foundation.pdf └── JavaFX-Programming-Cookbook.pdf ├── AutoUpdatingGui ├── Assets │ ├── Demo.gif │ ├── creatingScene.mp4 │ ├── dataFlow.PNG │ ├── gui.PNG │ └── projectStructure.PNG ├── README.md └── src │ └── sample │ ├── Main.java │ ├── controllers │ └── Controller.java │ ├── data │ └── Database.java │ ├── network │ └── Server.java │ └── viewFXML │ └── sample.fxml ├── DatabaseIntegration ├── Assets │ ├── afterDB.PNG │ └── beforeDB.PNG ├── Database │ └── Users.db ├── README.md └── src │ └── com │ └── tamimehsan │ └── Main.java ├── P2P ├── Assets │ ├── Connection.gif │ ├── Working.gif │ ├── folder.PNG │ ├── serverSet.PNG │ └── singletonDeclaration.PNG ├── README.md ├── ServerJava │ ├── .idea │ │ ├── .gitignore │ │ ├── description.html │ │ ├── encodings.xml │ │ ├── misc.xml │ │ ├── modules.xml │ │ ├── project-template.xml │ │ └── vcs.xml │ ├── ServerJava.iml │ ├── out │ │ └── production │ │ │ └── ServerJava │ │ │ └── com │ │ │ └── tamimehsan │ │ │ ├── Main.class │ │ │ └── network │ │ │ ├── Server$1.class │ │ │ └── Server.class │ └── src │ │ └── com │ │ └── tamimehsan │ │ ├── Main.java │ │ └── network │ │ └── Server.java └── client │ ├── .idea │ ├── .gitignore │ ├── description.html │ ├── encodings.xml │ ├── misc.xml │ ├── modules.xml │ ├── project-template.xml │ └── vcs.xml │ ├── client.iml │ ├── out │ └── production │ │ └── client │ │ └── com │ │ └── tamimehsan │ │ └── network │ │ ├── Client$1.class │ │ └── Client.class │ └── src │ └── com │ └── tamimehsan │ ├── ClientMain.java │ └── network │ └── Client.java ├── README.md ├── SendingFIleAndImage ├── README.md └── TransferObject.java ├── Socket-String-IO ├── README.md └── src │ └── com │ └── tamimehsan │ ├── Client.java │ └── Server.java └── UsingSceneBuilder └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | **/*.exe 2 | **/*.iml 3 | **/.idea 4 | **/out -------------------------------------------------------------------------------- /Assets/Java Server Side Programming - The Conceptual Foundation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TamimEhsan/JavaFX-Basics/335ec8356d909c5497f2c83ed78ee1c419ffc655/Assets/Java Server Side Programming - The Conceptual Foundation.pdf -------------------------------------------------------------------------------- /Assets/JavaFX-Programming-Cookbook.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TamimEhsan/JavaFX-Basics/335ec8356d909c5497f2c83ed78ee1c419ffc655/Assets/JavaFX-Programming-Cookbook.pdf -------------------------------------------------------------------------------- /AutoUpdatingGui/Assets/Demo.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TamimEhsan/JavaFX-Basics/335ec8356d909c5497f2c83ed78ee1c419ffc655/AutoUpdatingGui/Assets/Demo.gif -------------------------------------------------------------------------------- /AutoUpdatingGui/Assets/creatingScene.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TamimEhsan/JavaFX-Basics/335ec8356d909c5497f2c83ed78ee1c419ffc655/AutoUpdatingGui/Assets/creatingScene.mp4 -------------------------------------------------------------------------------- /AutoUpdatingGui/Assets/dataFlow.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TamimEhsan/JavaFX-Basics/335ec8356d909c5497f2c83ed78ee1c419ffc655/AutoUpdatingGui/Assets/dataFlow.PNG -------------------------------------------------------------------------------- /AutoUpdatingGui/Assets/gui.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TamimEhsan/JavaFX-Basics/335ec8356d909c5497f2c83ed78ee1c419ffc655/AutoUpdatingGui/Assets/gui.PNG -------------------------------------------------------------------------------- /AutoUpdatingGui/Assets/projectStructure.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/TamimEhsan/JavaFX-Basics/335ec8356d909c5497f2c83ed78ee1c419ffc655/AutoUpdatingGui/Assets/projectStructure.PNG -------------------------------------------------------------------------------- /AutoUpdatingGui/README.md: -------------------------------------------------------------------------------- 1 | # Auto Update GUI 2 | 3 | ## Basics 4 | 5 | In this I will show how to auto update JavaFX gui using ObservableArrayList and List view with worker thread and gui thread. 6 | 7 | - Creating a basic gui in scene builder 8 | - Adding references to gui elements in controller 9 | - Updating gui from Application thread and worker thread 10 | - Getting selected index from view 11 | - Deleting data from View 12 | 13 | ## Data Flow 14 | 15 | ![](https://raw.githubusercontent.com/TamimEhsan/JavaFX-Basics/master/AutoUpdatingGui/Assets/dataFlow.PNG) 16 | 17 | I usually use this model. I don't know if this even has any name or not. But i guess it kinda resembles MVC and Room. 18 | 19 | Here the network never communicated directly with the application or the controller. This is due to the reason we can not update gui from any worker thread. Thus we ensure unwanted change in gui. 20 | 21 | The application interface or gui is controlled by the controller. The application interface is designed in FXML by scene builder. And every business model is implemented in controllers. 22 | 23 | When network brings new update from server , it stores that in storage. And storage notify the controller for a data change and thus the controller will change the gui accordingly. 24 | 25 | This flow is pretty safe and is easy to understand for me. 26 | 27 | ## Project Tree 28 | 29 | ![](https://raw.githubusercontent.com/TamimEhsan/JavaFX-Basics/master/AutoUpdatingGui/Assets/projectStructure.PNG) 30 | 31 | Like before, the files of this one is also divided in several packages for a better environment and look. I have a controllers package for all the controllers. But now I have only one in each package. viewFXML for fxml designs, network package for everything related to networking, data package for storing data. 32 | 33 | ### Singeltons 34 | 35 | Here I have the networking classes and Database (the name has nothing to do with actual sql or no sql database). Like before this ensures that only one entity is created. 36 | 37 | 38 | 39 | ## Creating a GUI 40 | 41 | ![](https://raw.githubusercontent.com/TamimEhsan/JavaFX-Basics/master/AutoUpdatingGui/Assets/gui.PNG) 42 | 43 | The gui is pretty basic. In the left side we have a ListView which will used for auto update. We also have two buttons for adding and deleting data to and from view. And two labels for showing which item is selected. This is a [demo video](https://github.com/TamimEhsan/JavaFX-Basics/blob/master/AutoUpdatingGui/Assets/creatingScene.mp4) showing how this was created in scenebuilder: 44 | 45 | How to install Scenebuilder: 46 | 47 | ## Adding reference to gui elements 48 | 49 | Notice the fact that we have added a fx:id in some elements of the gui and some has event listeners. 50 | 51 | ```java 52 | @FXML 53 | private ListViewtextList; 54 | @FXML 55 | private Label selectedLabel; 56 | ``` 57 | 58 | We access the elements from controllers by this process. Here the listview is the ref of the table or whatever you call it. You can find a shit ton of tutorials explaining them. 59 | 60 | We also have event listeners for buttons and listView. 61 | 62 | ***Event Listeners*** listens for any specified predefined action and then will act accordingly. LIke when we click a button the onClickListener is called. Then inside that we can do whatever we like. But fxml does this easier for us. 63 | 64 | We have three methods 65 | 66 | ```java 67 | public void initialize(); 68 | public void addNew(); 69 | public void deleteList(); 70 | ``` 71 | 72 | The initialize() method is called when that class is initialized at first. This can be used to initialize variables. 73 | 74 | We will take a pause and check our data storage now. 75 | 76 | 77 | 78 | ## Data Storage 79 | 80 | It is pretty simple. At first we implemented the basic singleton structure. 81 | 82 | ```java 83 | private static Database instance; 84 | private ObservableList observableList; 85 | private Database(){ 86 | observableList = FXCollections.observableArrayList(); 87 | } 88 | 89 | public static Database getInstance(){ 90 | if( instance == null ){ 91 | instance = new Database(); 92 | } 93 | return instance; 94 | } 95 | ``` 96 | 97 | But here we have a observablelist. This will play the main part for auto updating. This is like simple arraylist. And adding and deleting data from it is like arraylist too. So it's simple. 98 | 99 | In database class we also have some methods to alter the data inside database ie the observableList. 100 | 101 | 102 | 103 | ## Binding observable list with list view 104 | 105 | In initialize method of controller class we use this to ask the list view to observe data change inside the observable list 106 | 107 | ```java 108 | textList.setItems(Database.getInstance().getObservableList()); 109 | ``` 110 | 111 | That's it! We are done with binding. 112 | 113 | 114 | 115 | ## Updating the list from gui 116 | 117 | By updating I mean updating the observable list. We will never touch the listView directly. May be in JavaFX this is no big deal, But this is good practice and this is must for many structures. 118 | 119 | We will update the observable list from application thread once and then from worker thread (this will resemble the networking part). 120 | 121 | ```java 122 | public void addNew(){ 123 | Database.getInstance().addItems("Added from Gui. Value="+count); 124 | count = count+1; 125 | } 126 | ``` 127 | 128 | Addnew method is called whenever we press the add new button. Cause we added a event listener to it. Notice we changed only the observable list. 129 | 130 | Now the fun part 131 | 132 | ## Updating list from thread 133 | 134 | **WE CAN"T UPDATE OR CHANGE ANYHTING IN GUI FROM THREAD** 135 | 136 | from main method we called a loop which will sleep for some time then add data to list. This is to resemble incoming data from socket 137 | 138 | ```java 139 | Server.getInstance().loop(); 140 | ``` 141 | 142 | And the loop has a thread which overrides run 143 | 144 | ```java 145 | public void loop(){ 146 | new Thread(){ 147 | @Override 148 | public void run() { 149 | for(int i=0;i<5;i++){ 150 | try { 151 | sleep(1000); 152 | } catch (InterruptedException e) { 153 | e.printStackTrace(); 154 | } 155 | // We will add the updating code here 156 | } 157 | } 158 | }.start(); 159 | } 160 | ``` 161 | 162 | It is pretty simple thread. 163 | 164 | But as we are inside a thread we can't change anything from this. Although it might seem like we are changing observable list. But that has a notify which will be called from thread. Although the application runs perfectly. But it will generate errors. 165 | 166 | ```java 167 | Platform.runLater( 168 | new Runnable() { 169 | @Override 170 | public void run() { 171 | Database.getInstance().addItems("Added from Network. Value="+count); 172 | count++; 173 | } 174 | } 175 | ); 176 | ``` 177 | 178 | 179 | 180 | We will use this snippet to update the observable list. Platform.runlater creates a request to application thread to run the code inside it later. There are other ways to update gui too! Like using an animation timer. But as there will less update we can get away with this one easily. 181 | 182 | And we are done with adding data. 183 | 184 | 185 | 186 | ## Deleting data from list 187 | 188 | List view has a method which will return the selected item index of the list. We will use that and delete that index from the observable list. As we will do this inside application thread we don't need Platform.runlater. 189 | 190 | ```java 191 | public void deleteList(){ 192 | int index = textList.getSelectionModel().getSelectedIndex(); 193 | if( index!=-1 ){ 194 | Database.getInstance().deleteItems(index); 195 | } 196 | } 197 | ``` 198 | 199 | It is pretty self explanatory too! 200 | 201 | Delete list method will be called when the delete button is clicked. We added some event handlers remember? 202 | 203 | 204 | 205 | That's it we are done for now. Run it and viola! 206 | 207 | 208 | 209 | ## Demo 210 | 211 | ![](https://raw.githubusercontent.com/TamimEhsan/JavaFX-Basics/master/AutoUpdatingGui/Assets/Demo.gif) 212 | 213 | 214 | 215 | Thank you making this far! 216 | 217 | 218 | 219 | > Written by 220 | > 221 | > Md. Tamimul Ehsan -------------------------------------------------------------------------------- /AutoUpdatingGui/src/sample/Main.java: -------------------------------------------------------------------------------- 1 | package sample; 2 | 3 | import javafx.application.Application; 4 | import javafx.fxml.FXMLLoader; 5 | import javafx.scene.Parent; 6 | import javafx.scene.Scene; 7 | import javafx.stage.Stage; 8 | import sample.network.Server; 9 | 10 | public class Main extends Application { 11 | 12 | @Override 13 | public void start(Stage primaryStage) throws Exception{ 14 | Parent root = FXMLLoader.load(getClass().getResource("viewFXML/sample.fxml")); 15 | primaryStage.setTitle("Hello World"); 16 | primaryStage.setScene(new Scene(root, 600, 400)); 17 | primaryStage.show(); 18 | 19 | Server.getInstance().loop(); 20 | } 21 | 22 | 23 | public static void main(String[] args) { 24 | launch(args); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /AutoUpdatingGui/src/sample/controllers/Controller.java: -------------------------------------------------------------------------------- 1 | package sample.controllers; 2 | 3 | import javafx.fxml.FXML; 4 | import javafx.scene.control.Label; 5 | import javafx.scene.control.ListView; 6 | import sample.data.Database; 7 | 8 | public class Controller { 9 | @FXML 10 | private ListViewtextList; 11 | @FXML 12 | private Label selectedLabel; 13 | 14 | private int count = 0; 15 | 16 | public void initialize(){ 17 | textList.setItems(Database.getInstance().getObservableList()); 18 | } 19 | 20 | public void addNew(){ 21 | Database.getInstance().addItems("Added from Gui. Value="+count); 22 | count = count+1; 23 | } 24 | 25 | public void deleteList(){ 26 | int index = textList.getSelectionModel().getSelectedIndex(); 27 | if( index!=-1 ){ 28 | Database.getInstance().deleteItems(index); 29 | } 30 | index = textList.getSelectionModel().getSelectedIndex(); 31 | if( index!=-1 ){ 32 | selectedLabel.setText(""+index); 33 | } 34 | } 35 | 36 | public void updateLabel(){ 37 | int index = textList.getSelectionModel().getSelectedIndex(); 38 | if( index!=-1 ){ 39 | selectedLabel.setText(""+index); 40 | } 41 | } 42 | 43 | public ListView getTextList(){ 44 | return textList; 45 | } 46 | public Controller getInstance(){ 47 | return this; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /AutoUpdatingGui/src/sample/data/Database.java: -------------------------------------------------------------------------------- 1 | package sample.data; 2 | 3 | import javafx.collections.FXCollections; 4 | import javafx.collections.ObservableList; 5 | 6 | public class Database { 7 | private static Database instance; 8 | private ObservableList observableList; 9 | private Database(){ 10 | observableList = FXCollections.observableArrayList(); 11 | } 12 | 13 | public static Database getInstance(){ 14 | if( instance == null ){ 15 | instance = new Database(); 16 | } 17 | return instance; 18 | } 19 | public ObservableList getObservableList(){ 20 | return observableList; 21 | } 22 | public void addItems(String s){ 23 | observableList.add(s); 24 | } 25 | public void deleteItems(int index){ 26 | observableList.remove(index); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /AutoUpdatingGui/src/sample/network/Server.java: -------------------------------------------------------------------------------- 1 | package sample.network; 2 | 3 | 4 | import javafx.application.Platform; 5 | import sample.data.Database; 6 | 7 | public class Server { 8 | private static Server instance; 9 | private int count = 1; 10 | private Server(){} 11 | 12 | public static Server getInstance(){ 13 | if( instance == null ){ 14 | instance = new Server(); 15 | } 16 | return instance; 17 | } 18 | public void loop(){ 19 | new Thread(){ 20 | @Override 21 | public void run() { 22 | for(int i=0;i<5;i++){ 23 | try { 24 | sleep(1000); 25 | } catch (InterruptedException e) { 26 | e.printStackTrace(); 27 | } 28 | Platform.runLater( 29 | new Runnable() { 30 | @Override 31 | public void run() { 32 | Database.getInstance().addItems("Added from Network. Value="+count); 33 | count++; 34 | } 35 | } 36 | ); 37 | } 38 | } 39 | }.start(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /AutoUpdatingGui/src/sample/viewFXML/sample.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |