JAVAFX how to update GUI elements (nodes)

13,854

You need to use a Task, if you have some long running operation. Otherwise when that operation is called from the JavaFX Application Thread it would block the GUI.

If you want to update the GUI from the Task you have to use Platform.runlater, which will run the code on the JavaFX Application Thread: Platform.runlater

Updates to the Nodes of your GUI have always to be performed on the JavaFx Thread.

When you update status inside the Listener of button it should work.

  button.setOnAction(evt -> {
        dbConnect();
        status.setText("Connected");
        // ...
    });

If dbConnect() takes some time, you can use a Task:

 Task<Void> longRunningTask = new Task<Void>() {

        @Override
        protected Void call() throws Exception {
            dbConnect();
            Platform.runLater(() -> status.setText("Connected"));
            return null;
        }
    };


    button.setOnAction(e -> {
        new Thread(longRunningTask).start();
    });
Share:
13,854
AnonymousGuy
Author by

AnonymousGuy

Updated on June 25, 2022

Comments

  • AnonymousGuy
    AnonymousGuy almost 2 years

    This question is already asked but i copuldnt udnerstand it. Imagine that. I have a program with 2 scenes. First scene1 is opened which is the scene for connection to database. There is a label called Status which should turn from "Disconnected" to "Connected" when the connection is established(by clicking the COnnect button). So i made a function to take the button "Connect" onClick event. This function is declared and defined inside a controller class (i am using fmxl designing with scene builder). So basicly i want to change the status to "COnnected" (status.setText("Connected")) from the connection function(method) which is inside the controller class. However when I do that, the text isn't changed instantly after the connection is established, but it changes when the scene is about to close and i am about to change the scene to the new one... I read on the internet and i saw that i should use Platform.runLater and threading so i tried:

    private void changeSC() throws IOException, InterruptedException, SQLException
    {
    
        dbConnect();
    
        Thread thrd = new Thread() {
    
            public void run() {
    
                     Platform.runLater(new Runnable() {
                         @Override public void run() {
                         status.setText("Connected");
                            status.setTextFill(Color.GREEN);
                         }});
            }
        };
        thrd.start();
    
        //pb.setProgress(1.0);
        Parent root = FXMLLoader.load(getClass().getResource("Design.fxml"));
        Scene primary = new Scene(root,1024,768);
        primary.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
        System.out.println("Text changing to COnnected");
        status.setTextFill(Color.GREEN);
        Thread.sleep(2000);
        Main.window.setScene(primary);
    
    }
    

    changeSC is the function that is executed when Connect button is clicked. This is my old version which also doesnt work:

    private void changeSC() throws IOException, InterruptedException, SQLException
    {
    
        dbConnect();
    
          status.setText("Connected");
          status.setTextFill(Color.GREEN);
    
    
        //pb.setProgress(1.0);
        Parent root = FXMLLoader.load(getClass().getResource("Design.fxml"));
        Scene primary = new Scene(root,1024,768);
        primary.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
        System.out.println("Text changing to COnnected");
        status.setTextFill(Color.GREEN);
        Thread.sleep(2000);
        Main.window.setScene(primary);
    
    }
    

    The problem is with the text which should change to "Connected". It changes just when my scene is about to be switched....

  • leobelizquierdo
    leobelizquierdo about 8 years
    you don't need to do Platform.runLater inside a Task. The Task offer a mechanism to listen when the task has finished, using events like setOnSucceeded and SetOnFailed.
  • leobelizquierdo
    leobelizquierdo about 8 years
    I don't understand, how you fixed it catching an event that means that your task (in case you are using one) has fail?