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?

5
  • please post full error log Commented Nov 7, 2017 at 6:00
  • That's only one error. Commented Nov 7, 2017 at 6:01
  • Why you are setting the text of output label under a new thread when controller is initializing?? Commented Nov 7, 2017 at 6:03
  • I wan't to update the Label automatically with thread. I know there's another method for that without using thread. But just for my learning purpose i'm using thread. Commented Nov 7, 2017 at 6:06
  • You can actually do this much easily, by using output.textProperty().bind(input.textProperty());. Commented Dec 20, 2020 at 13:20

2 Answers 2

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);
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

Can i get clue on final AtomicInteger count = new AtomicInteger(-1);
Well I would suggest read some great posts here : stackoverflow.com/questions/4818699/… 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
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).
@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.
2

Just use

Platform.runLater( () -> {
  output.setText(input.getText());
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.