title: How to update status and progress from a seperate thread in JavaFX
body: <p>I need to be able to call a separate thread. The thread analysis a file and pull stats from that. </p>
  
  <p>The analyzing of the file can take up to 2 minutes and during the analysis data is printed to the logs.</p>
  
  <p>I would like to have a TextArea on the front end that needs to print out the analysis (as it analysis) and I would also like to have a progress bar to indicate the progress. All of this is determined inside the separate thread.</p>
  
  <p>What I have done is creating a method in the UI class to add a string to the Text Area and pass in a reference of this class to the launched thread. </p>
  
  <p>My Main Class</p>
  
  <pre><code>package trymutilthread;
  
  import javafx.application.Application;
  import javafx.application.Platform;
  import javafx.concurrent.Task;
  import javafx.event.ActionEvent;
  import javafx.event.EventHandler;
  import javafx.scene.Scene;
  import javafx.scene.control.Button;
  import javafx.scene.control.TextArea;
  import javafx.scene.layout.StackPane;
  import javafx.scene.layout.VBox;
  import javafx.stage.Stage;
  
  public class TryMutilThread extends Application {
  
      TextArea ta;
  
      public static void main(String[] args) {
          launch(args);
      }
  
      @Override
      public void start(Stage primaryStage) {
          Button btn = new Button();
          btn.setText("Start");
          btn.setOnAction(new EventHandler&lt;ActionEvent&gt;() {
              @Override
              public void handle(ActionEvent event) {
                  startScheduledExecutorService();
              }
          });
  
          ta = new TextArea();        
  
          VBox vBox = new VBox();
          vBox.getChildren().addAll(btn, ta);
  
          StackPane root = new StackPane();
          root.getChildren().add(vBox);
  
          Scene scene = new Scene(root, 300, 750);
  
          primaryStage.setScene(scene);
          primaryStage.show();
      }
  
      private void startScheduledExecutorService() {
          final TryMutilThread classI = this;
  
          Task&lt;Void&gt; task = new Task&lt;Void&gt;() {
              @Override protected Void call() throws Exception {
                  try {
                      ta.appendText("Starting Thread\n");
                      new SomeProcess(classI).doTheLogic();
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
                  return null;
              }
          };
  
          Thread th = new Thread(task);
          th.setDaemon(true);
          th.start();      
      }
  
      public void appendText(String string) {        
          ta.appendText(string);
      }
  }   
  </code></pre>
  
  <p>The class that is executed in the thread</p>
  
  <pre><code>package trymutilthread;
  
  public class SomeProcess {
  
      TryMutilThread taClass = null;
  
      public SomeProcess (TryMutilThread taClass) {
          this.taClass = taClass;
      }
  
      public void doTheLogic() throws Exception{        
          taClass.appendText("Staring Thread");        
  
          for (int i = 0; i &lt; 5000; i++) {
              taClass.appendText(String.valueOf(i));
          }
  
          taClass.appendText("Ending Thread");
      }
  }
  </code></pre>
  
  <p>Now when I execute this it still only output the text to the TextArea once the thread has ended.</p>
  
  <p>I did had a look at the following 2 posts:</p>
  
  <p><a href="https://stackoverflow.com/questions/18597644/javafx-update-textarea">JavaFX update textArea</a></p>
  
  <p><a href="https://stackoverflow.com/questions/19192574/java-client-server-thread-null-pointer-exception-when-quickly-communicating-me">Java client / server thread null pointer exception when quickly communicating messages</a></p>
  
  <p>I am not able to get the data printed to logs until the process has ended. </p>
  
  <hr>
  
  <p>I updated my code to create a Task.
  But now I am getting the following error when it executes</p>
  
  <pre><code>Executing com.javafx.main.Main from F:\DEV\Projects\TryMutilThread\dist\run404234128\TryMutilThread.jar using platform C:\Program Files\Java\jdk1.7.0_10/bin/java
  java.lang.NullPointerException
      at com.sun.javafx.sg.prism.NGTextHelper$TextAttributes.computeLinePadding(NGTextHelper.java:405)
      at com.sun.javafx.sg.prism.NGTextHelper$TextAttributes.access$200(NGTextHelper.java:292)
      at com.sun.javafx.sg.prism.NGTextHelper.buildTextLines(NGTextHelper.java:2357)
      at com.sun.javafx.sg.prism.NGTextHelper.validateText(NGTextHelper.java:1847)
      at com.sun.javafx.sg.prism.NGTextHelper.getCaretShape(NGTextHelper.java:1435)
      at javafx.scene.text.Text.getDecorationShapes(Text.java:1150)
      at javafx.scene.text.Text.impl_geomChanged(Text.java:757)
      at javafx.scene.text.Text$1.invalidated(Text.java:214)
      at javafx.beans.property.StringPropertyBase.markInvalid(StringPropertyBase.java:127)
      at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:161)
      at javafx.beans.property.StringPropertyBase.set(StringPropertyBase.java:67)
      at javafx.scene.text.Text.setText(Text.java:188)
      at com.sun.javafx.scene.control.skin.TextAreaSkin$17.invalidated(TextAreaSkin.java:610)
      at com.sun.javafx.binding.ExpressionHelper$Generic.fireValueChangedEvent(ExpressionHelper.java:359)
      at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100)
      at javafx.scene.control.TextInputControl$TextProperty.fireValueChangedEvent(TextInputControl.java:1034)
      at javafx.scene.control.TextInputControl$TextProperty.markInvalid(TextInputControl.java:1038)
      at javafx.scene.control.TextInputControl$TextProperty.invalidate(TextInputControl.java:978)
      at javafx.scene.control.TextInputControl$TextProperty.access$200(TextInputControl.java:950)
      at javafx.scene.control.TextInputControl$1.invalidated(TextInputControl.java:119)
      at com.sun.javafx.binding.ExpressionHelper$SingleInvalidation.fireValueChangedEvent(ExpressionHelper.java:155)
      at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:100)
      at javafx.scene.control.TextArea$TextAreaContent.insert(TextArea.java:196)
      at javafx.scene.control.TextInputControl.replaceText(TextInputControl.java:373)
      at javafx.scene.control.TextInputControl.insertText(TextInputControl.java:308)
      at javafx.scene.control.TextInputControl.appendText(TextInputControl.java:298)
      at trymutilthread.TryMutilThread.appendText(TryMutilThread.java:80)
      at trymutilthread.SomeProcess.doTheLogic(SomeProcess.java:26)
      at trymutilthread.TryMutilThread$2.call(TryMutilThread.java:66)
      at trymutilthread.TryMutilThread$2.call(TryMutilThread.java:62)
      at javafx.concurrent.Task$TaskCallable.call(Task.java:1259)
      at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334)
      at java.util.concurrent.FutureTask.run(FutureTask.java:166)
      at java.lang.Thread.run(Thread.java:722)
  </code></pre>
  
  <p>I then google'd the error and it seems that I need to put the interaction code in a Platform.runlater().</p>
  
  <p><a href="https://stackoverflow.com/questions/19192574/java-client-server-thread-null-pointer-exception-when-quickly-communicating-me">Java client / server thread null pointer exception when quickly communicating messages</a></p>
  
  <p>I changed the class to execute the thread to be </p>
  
  <pre><code>package trymutilthread;
  
  import javafx.application.Platform;
  
  public class SomeProcess {
  
      TryMutilThread taClass = null;
  
      public SomeProcess(TryMutilThread taClass) {
          this.taClass = taClass;
      }
  
      public void doTheLogic() throws Exception {
          taClass.appendText("Staring Thread");
  
          for (int i = 0; i &lt; 5000; i++) {
              //remove this append line
              //taClass.appendText(i + "\n");                
              //And replaced it with platform.runlater
              Platform.runLater(new Runnable() {
                  @Override
                  public void run() {
                      taClass.appendText("AGREED" + "\n");
                  }
              });
          }
  
          taClass.appendText("Ending Thread");
      }
  }
  </code></pre>
  
  <p>It executes without any errors but now it seems to be back to the start... The UI is frozen until all is added to the TextArea</p>