I am using a background Thread
to run my loading code and wish to bind the MessageProperty
of the Task
to a label.
However, when calling updateMessage()
the task hangs; the message is never updated and the next line of code does not execute.
This is using JDK 1.10.1. Here is an MCVE:
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
VBox root = new VBox(10);
Label label = new Label("Message");
root.getChildren().add(label);
primaryStage.setScene(new Scene(root));
Task loadingTask = new LoadingTask();
Thread loadingThread = new Thread(loadingTask);
loadingThread.setDaemon(true);
label.textProperty().bind(loadingTask.messageProperty());
loadingThread.start();
primaryStage.setWidth(200);
primaryStage.setHeight(200);
primaryStage.show();
}
}
class LoadingTask<Void> extends Task {
@Override
protected Object call() throws Exception {
System.out.println("Loading task ...");
updateMessage("Loading task ...");
System.out.println("Message: " + getMessage());
return null;
}
}
The output:
Loading task ...
The second System.out.println()
is never executed.
Edit:
I added a simple GUI to my MCVE with a label bound to the MessageProperty
. The label does get updated to show "Loading task ..." but the console output remains the same; code after the updateMessage()
method is called does not execute.
2nd Edit:
I ran my step debugger, and an IllegalStateException
is being thrown from the Task
class: "Task must only be used from the FX Application Thread"
I'm not sure what that means as the whole point is to run this task on a different thread...
Your only issue is, that you must not access getMessage()
from another thread than the FX UI-Thread. Try Platform.runLater(() -> System.out.println("Message: " + getMessage()));