title: Updating the JavaFx Gui with threads and or Tasks
body: <p>I am creating a chat program that contains a GUI that I have created in the new version of the JavaFx Scene builder. I have a main method that extends application and i have a simpleController (that controls all the buttons, labels, anchorPanes, etc) in my GUI.</p>
  
  <p>Other than that, I have a server application that can receive and send messages. For this purpose, I have created the following simple protocol:</p>
  
  <p><strong><em>Commands / Description:</em></strong></p>
  
  <ul>
  <li>1 - Ask for permission to connect and at the same time, ask for a user
  ID (server finds out how many users are online and adds the id+1)</li>
  <li>2 - Chat, the client sends an ID and a String message (Example: 21<br>
  Hello (note all of these are on a separate line))</li>
  <li>3 - Disconnects the client.</li>
  <li>4 - Shows a list of all the clients online.</li>
  <li>5 - Ask who else is online (this is only used when a user is
  connecting and he needs to know how many users are online in order to
  update the GUI).</li>
  <li>10 - Error of all sorts if the server returns the 10 message it means
  that the call the client just did was an error or that it could not<br>
  be completed!  </li>
  </ul>
  
  <p>Using this simple logic, it should be fairly easy for me to make users connect, chat and disconnect. However, it turned out that what should have been a simple task has turned out to be my worst nightmare. </p>
  
  <p>So far my users has no problem connecting to the program and more users can connect at the same time. </p>
  
  <p>Where things start to get tricky is when I want to send and receive messages between server and client.</p>
  
  <p>I do not know how I can update my GUI while using a thread. I have tried to read up on the Task class, but I am unable to see <strong>whether this should be used instead of a thread or the thread should have this as a parameter</strong>. </p>
  
  <p>Should I create a new class that listens for input and make that class extend thread?   <strong>OR</strong><br>
  Should the thread be running in my simpleController class?</p>
  
  <p><strong>Main</strong></p>
  
  <pre><code>public class Main extends Application{
      public static void main(String[] args) throws IOException{
          Application.launch(Main.class, (java.lang.String[]) null);
      }
  
      @Override
      public void start(Stage primaryStage) throws Exception {
          try {
              AnchorPane page = (AnchorPane) FXMLLoader.load(Main.class.getResource("testingBackground.fxml"));
              Scene scene = new Scene(page);
              primaryStage.setScene(scene);
              primaryStage.setTitle("Chatten");
              primaryStage.show();
  
          } catch (Exception ex) {
              java.util.logging.Logger.getLogger(Main.class.getName()).log(
                      java.util.logging.Level.SEVERE, null, ex);
          }
      }
  }
  </code></pre>
  
  <p><strong>simpleController</strong></p>
  
  <pre><code>import java.io.IOException;
  import java.io.PrintWriter;
  import java.net.InetAddress;
  import java.net.Socket;
  import java.net.UnknownHostException;
  import java.util.ArrayList;
  import java.util.Scanner;
  import java.io.IOException;
  import java.net.URL;
  import java.util.ResourceBundle;
  
  import com.sun.glass.ui.Platform;
  
  import javafx.beans.value.ChangeListener;
  import javafx.beans.value.ObservableValue;
  import javafx.concurrent.Task;
  import javafx.event.ActionEvent;
  import javafx.event.EventHandler;
  import javafx.fxml.Initializable;
  import javafx.scene.control.Button;
  import javafx.scene.control.Label;
  import javafx.scene.control.TextArea;
  import javafx.scene.control.TextField;
  import javafx.scene.image.Image;
  import javafx.scene.image.ImageView;
  import javafx.scene.layout.AnchorPane;
  import javafx.scene.text.Text;
  
  /*
   * evt ret array listen med commands da jeg selv kan styre hvilke commands der kommer ind og ud! og brugeren faktisk
   * aldrig selv kan vælge!
   */
  public class SimpleController extends Thread implements Initializable{
      public Button btn_Connect;
      public AnchorPane pictureFrame;
      public Socket socket = new Socket();
      public PrintWriter pw;
      public Scanner input;
      public int clientId = 1;
      public Client client = new Client(socket, pw, input, clientId);
      // options!
      public TextField txt_userName;
      public TextField textField_chat;
      // send button
      public Button Send;
      /*
       * current client that the user i connected with, this client is used to send commands and tell other clients who is connected on
       * what "ingame chat persons"
       */
      public static int currentClientId;
      // chatperson username
      public Label lbl_userName2;
      public Label lbl_userName3;
      public Label lbl_chatPerson2;
      public Label lbl_Chatperson1_userName;
      //Pictures of chat person
      public Label chatPerson3;
      public Label chatPerson1;
      // chat persons textfield
      public TextArea txt_ChatPerson1;
      //public TextField txt_ChatPerson1;
      public TextField txt_ChatPerson2;
      public TextField txt_ChatPerson3;
  
  
      @Override
      public void initialize(URL location, ResourceBundle resources) throws NullPointerException {
          try {
              client.connect();
          } catch (IOException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
          pictureFrame.setMaxSize(409, 373);
          txt_ChatPerson1.setMinWidth(50);
          txt_ChatPerson1.setPrefWidth(50);
          txt_ChatPerson1.setMaxWidth(300);
          txt_ChatPerson1.setText("         ");
  
  
  
          btn_Connect.setOnAction(new EventHandler&lt;ActionEvent&gt;() {   
              @Override
  
              public void handle(ActionEvent event) throws NullPointerException {
                  connectMeWithOthers(1);
              }
          });
  
          Send.setOnAction(new EventHandler&lt;ActionEvent&gt;() {
  
              // WORK IN PROGReSS!!
              @Override
              public void handle(ActionEvent event) {
  
                  /*
                   * new line code:
                   */
                  String x = textField_chat.getText();
                  txt_ChatPerson1.setText(x);
                  txt_ChatPerson1.setVisible(true);
                  System.out.println("x" +x);
  
                  txt_ChatPerson1.textProperty().addListener(new ChangeListener&lt;String&gt;() {
  
                      @Override
                      public void changed(
                              ObservableValue&lt;? extends String&gt; observable,
                              String oldValue, String newValue) {
  
  
                          //  txt_ChatPerson1.setPrefRowCount(5);
                          txt_ChatPerson1.setPrefWidth(txt_ChatPerson1.getText().length()*7);
                          //txt_ChatPerson1.setPrefHeight(txt_ChatPerson1.getText().length()*3);
                      }
                  });
                  txt_ChatPerson1.autosize();
                  client.SendChat(x);
              }
          });
      }
  
      /**
       * this method connect the client to the other clients who are online on the server!
       * the method calls it self after the user has established connection in order to load the other chat persons online
       * if the client is the online user online then it will only load the user
       * @param id
       */
      protected void connectMeWithOthers(int id) {
          try {
              int responseId = client.sendCommando(id);
              System.out.println(" response id "+responseId);
              // finds whom is connected and tries to connect to a spot that is avalibul!
              //Response is the ID of the chat persons
              switch (responseId) {
              case 1:
                  currentClientId = client.reciveCommando();
                  client.setClientId(currentClientId);
                  client.sendString(txt_userName.getText());
                  connectMeWithOthers(5);
                  break;  
              case 5:
                  int times = client.reciveCommando();
                  int o = 0;
                  System.out.println("times: "+times);
  
                  while (o != times) {
                      int j = client.reciveCommando();
                      System.out.println("j"+ j);
                      String name = client.reciveString();
                      System.out.println("Name " +name);
                      createUser(j, name);    
                      o++;
                  }
                  start();
                  break;
  
              case 10:
                  System.out.println("Connection fail chat room is full! Please try again later!");
  
              case 8:
                  start();
                  break;
              default:
                  break;
              }
  
          } catch (IOException e) {
              // TODO Auto-generated catch block
              e.printStackTrace();
          }
  
      }
      private void createUser(int j, String reciveChat) {
          if (j == 1) {
              chatPerson1.setVisible(true);
              lbl_Chatperson1_userName.setVisible(true);
              lbl_Chatperson1_userName.setText(reciveChat);
  
          }else if (j == 2) {
              lbl_chatPerson2.setVisible(true);
              lbl_userName2.setVisible(true);
              lbl_userName2.setText(reciveChat);
          }else if (j == 3){
              chatPerson3.setVisible(true);
              lbl_userName3.setVisible(true);
              lbl_userName3.setText(reciveChat);
          }else {
              Image img = new Image(getClass().getResourceAsStream("Figur.png"));
              Label test2 = new Label("", new ImageView(img));
              test2.setLayoutX(50);
              test2.setLayoutY(30);
              test2.setPrefSize(1000, 1000);
              pictureFrame.getChildren().addAll(test2);
              test2.setVisible(true);
          }
  
      }
      /*
       * denne metode er en rewrite af run metoden.
       */
      public void StartClient(){
          ClientListner cl = new ClientListner(client);
  
          Task task = new Task&lt;String&gt;() {
  
              @Override
              protected String call() throws Exception {
                  // TODO Auto-generated method stub
  
                  return null;
              }
          };
          Thread t = new Thread(task);
          cl.start();
          while (true) {
              if (cl.recived) {
  
              }
          }
      }
  
      /*
       * Run metoden er brugt til at recive data fra andre users og update GUI'en skal muligvis rewrites!?
       * 
       */
  
  
      public void run(){ 
          System.out.println("Thread started");
          System.out.println(client.getSocket().isConnected());
          ClientListner cl = new ClientListner(client);
          while (client.getSocket().isConnected()) {
              int key = 10;
              if (cl.recived) {
  
                  try {
                      key = client.reciveCommando();
                      System.out.println("jeg er her");
                  } catch (IOException e) {
                      // TODO Auto-generated catch block
                      e.printStackTrace();
                  }
              }
  
  
              System.out.println("Key "+key);
              switch (key) {
              // case 2 er recive chat:
              case 2:
                  // først find ud af hvilket ID der har sendt chatten:
                  int y = 0;
                  try {
                      y = client.reciveCommando();
                      System.out.println("y" + y); 
                  } catch (IOException e) {
                      // TODO Auto-generated catch block
                      e.printStackTrace();
                  }
                  // derefter få beskeden og send den så ud til resten.
                  String says = client.reciveChat().toString();
                  if (y == 1) {
                      txt_ChatPerson1.setText(client.reciveChat());
                  }else if (y == 2) {
  
                  }else {
                      chatPerson3.setVisible(true);
                      txt_ChatPerson3.setVisible(true);
                      txt_ChatPerson3.setText(client.reciveChat());
                  }
  
                  break;
  
              default:
                  break;
              }
          }
      }
  
  }
  </code></pre>
  
  <p><strong>Client</strong></p>
  
  <pre><code>import java.io.IOException;
  import java.io.PrintWriter;
  import java.net.InetAddress;
  import java.net.Socket;
  import java.util.Scanner;
  public class Client {
  // disse var static
      public final static int portNumber = 6040;
      public Socket socket;
      private PrintWriter pw;
      private Scanner input;
      private int clientId;
      /**
       * @param args
       * @throws IOException 
       */
  
      public Client(Socket socket, PrintWriter pw, Scanner input, int clientId){
          this.socket = socket;
          this.pw = pw;
          this.input = input;
          this.clientId = clientId;
      }
      public void connect() throws IOException{
          // du kan vælge at bruge inetadressen til at connecte i socketet.
          InetAddress adr = InetAddress.getByName("localhost");
          socket = new Socket("localhost", portNumber);
          input=new Scanner(socket.getInputStream());
          pw = new PrintWriter(socket.getOutputStream());
      }
      /**
       * This method sends the message (that the client(chat person) writes to the user)
       * @param x
       * @throws NullPointerException
       * @throws IOException 
       */
      public void SendChat(String x) throws NullPointerException{
              pw.println(2);
              pw.flush();
              pw.println(SimpleController.currentClientId);
              pw.flush();
              pw.println(x);
              pw.flush(); 
  
      }
      public int sendCommando(int id) throws IOException{
          System.out.println("Jeg sender"+ id);
          pw.println(id);
          pw.flush();
          /*
           * this part of the program sends a command to the server if the command is 1 then 1 is = Connect.
           * the program then ask the server is the server is full or is it ok to connect? 
           * if the response is not 10 then the program will allow a connection to happen the return type will be the Id of which 
           * the chat person becomes!
           */
          // should the method return 0 the Application will do NOTHING!
          switch (id) {
          case 1:
      int k = reciveCommando();
              if (k== 10) {
                  return 10;
              }else if (k &lt; 3) {
                  System.out.println("returned k" + k);
                  return k;
              }else {
  
              return 10;
              }
              /*
               * Closes the connection with the server!
               */
          case 3:
  
              socket.close();
              return 0;
  
          case 5:
              int y  = reciveCommando();
              return y;
          default:
              return 0;
          }
  
      }
      /*
       * this method recives a command from the server! the comands can be found in the ChatCommands.txt
       * returns the command as an integer!
       */
      public int reciveCommando() throws IOException{
          Integer i = input.nextInt();
          return i;
      }
      /**
       * Gets a String response from the server. This method i used to create other users and give them the correct username.
       * 
       * @param i
       * @return
       * @throws IOException
       */
      public String getStringResponse(int i) throws IOException {
          pw.print(i);
          pw.flush();
          String x = input.nextLine();
          return x;
  
      }
      /*
       * Work in progress - client getter og setter methoder!
       */
  
      public Socket getSocket(){
          return socket;
      }
      public Scanner getInput(){
          return input;
      }
      public PrintWriter getPw(){
          return pw;
      }
      public int getClientId(){
          return clientId;
      }
  
      public void setClientId(int i ){
          clientId = i;
      }
      public String reciveChat(){
          String x = getInput().next();
          return x;
      }
      public String reciveString(){
          String x =input.next();
          return x;
      }
      public void sendString(String x){
          pw.println(x);
          pw.flush();
      }
  
  }*
  </code></pre>
  
  <p>I am really sorry about the code being kind of messy. The run() method in the simple controller was an attempt to make a thread of the simpleController. However, this did not work as I expected. :(</p>
  
  <p>The main goal of this is basically to make sure that the two people in the chat room can chat together. So, all it has to do is update 1 or 2 textareas.</p>