JAVAFX how to update GUI elements (nodes)
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();
});
AnonymousGuy
Updated on June 25, 2022Comments
-
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 about 8 yearsyou don't need to do
Platform.runLater
inside aTask
. TheTask
offer a mechanism to listen when the task has finished, using events likesetOnSucceeded
andSetOnFailed
. -
leobelizquierdo about 8 yearsI don't understand, how you fixed it catching an event that means that your task (in case you are using one) has fail?