6

Actually i'm a beginner to the java thread. For my learning purpose I've created a simple program. I don't know where i missed.

Code:

package javaguithread;

import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;

public class Controller {

    Thread t1;

    @FXML
    TextField input;

    @FXML
    Label output;

    @FXML
    private void addData() {
        output.setText(input.getText());
    }

    public void initialize() {

        t1 = new Thread(() -> {

            while (true) {
                System.out.println(input.getText());
                output.setText(input.getText());
            }
        });

        t1.start();
    }
}

Error it show is

at com.sun.javafx.tk.Toolkit.checkFxUserThread(
Toolkit.java:236)

Updated

I've tried initializing the thread with the another class I've created. Hers's my code.

package javathreadgui;

import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;

public class Controller {

    private class GuiUpdater extends Task<Void> {

        Controller ctrl;

        GuiUpdater(Controller ctrl) {
            this.ctrl = ctrl;
        }

        @Override
        protected Void call() throws Exception {
            makeChanges();
            return null;
        }

        private void makeChanges(){
         while(true){
             Platform.runLater(() -> {
               ctrl.output.setText(ctrl.input.getText());  
             });

             System.out.println("test");

         }   
        }

    }

    @FXML
    TextField input;

    @FXML
    Label output;

    public void initialize() {
        System.out.println("Hello ");

        Task<Void> task = new GuiUpdater(this);

        Thread thread = new Thread(task);

        thread.setDaemon(true);
        thread.start();
    }

}

It works preety well when i make console output as

System.out.println("test");

else the GUI freezes. What can i do for that?

Surya Bhusal
  • 520
  • 2
  • 8
  • 28

2 Answers2

12

Any UI changes has to take place on the JavaFX Thread. Wrap your setText() call with the code below :

Platform.runLater(new Runnable() {
      @Override public void run() {
           output.setText(input.getText());
      }
});

There are tons of post you can search about concurrency and how you can update UI through task/threads. But you if you don't really want to dig into details all you need to know is that every single UI update has to be inside a Platform.runLater(...) call.

Edit :

Here is an example that might help you :

import java.util.Scanner;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.stage.Stage;

public class LabelUpdateTest extends Application {

    private Label label;

    @Override
    public void start(Stage stage) throws Exception {
        label = new Label("Waiting for input..");
        stage.setScene(new Scene(label, 100, 100));
        stage.show();

        initInputThread();
    }

    private void initInputThread() {

        Scanner input = new Scanner(System.in);

        Task<Void> task = new Task<Void>() {
            @Override
            protected Void call() {
                while (true) {
                    String userInput = input.nextLine();

                    Platform.runLater(new Runnable() {
                        @Override
                        public void run() {
                            label.setText("Input was : " + userInput);
                        }
                    });

                }
            }
        };

        Thread th = new Thread(task);
        th.setDaemon(true);
        th.start();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
JKostikiadis
  • 2,847
  • 2
  • 22
  • 34
  • Can i get clue on final AtomicInteger count = new AtomicInteger(-1); – Surya Bhusal Nov 07 '17 at 06:53
  • Well I would suggest read some great posts here : https://stackoverflow.com/questions/4818699/practical-uses-for-atomicinteger But if you just want to update your UI through non javaFX threads don't over think about it, you only need to call the UI updates inside a Platform.runLater – JKostikiadis Nov 07 '17 at 07:00
  • Wait a second. Previously you had it running on a different Thread. Right now you just set an infinite While loop changing the Label's text. My code i gave you before was to make update of UI possible inside a non JavaFX thread ( ex Task , Thread etc). – JKostikiadis Nov 08 '17 at 14:18
  • @suryabhusal Check my post again. I added an example which you can update the content of the Label using the user input on a different thread. – JKostikiadis Nov 08 '17 at 14:26
2

Just use

Platform.runLater( () -> {
  output.setText(input.getText());
}
Sumsuddin Shojib
  • 3,583
  • 3
  • 26
  • 45