在活动场景图中对JavaFX节点进行的所有操作都必须在JavaFX应用程序线程上运行,否则您的程序可能无法正常工作。
当您尝试在JavaFX应用程序线程之外修改场景图节点的属性时,JavaFX将抛出异常IllegalStateException:Not on FX application thread
。即使您没有收到IllegalStateException,也不应该在JavaFX应用程序线程之外修改场景图节点,因为如果这样做,您的代码可能会失败不可预测。
使用Platform.runLater()
将操作场景图节点的代码包装在Platform.runLater调用中,以允许JavaFX系统在JavaFX应用程序线程上运行代码。
例如,您可以使用以下代码修复示例程序:
Platform.runLater(() -> label.setText(""))
使用带有message
属性的Task
的替代方法
如果您正在使用JavaFX Task,它具有一些内置支持使用JavaFX进行并发编程的功能,则可以利用其message属性,该属性可以安全地从任何线程更新,但仅在JavaFX线程上中继属性更改。
这是一个示例(来自Task javadoc):
Task<Integer> task = new Task<Integer>() {
@Override protected Integer call() throws Exception {
int iterations;
for (iterations = 0; iterations < 10000000; iterations++) {
if (isCancelled()) {
updateMessage("Cancelled");
break;
}
updateMessage("Iteration " + iterations);
updateProgress(iterations, 10000000);
}
return iterations;
}
};
你可以安全地绑定到消息属性,以便在UI中反映出更改的消息值:
Label iterationLabel = new Label();
iterationLabel.textProperty().bind(
task.messageProperty()
);
updateMessage
javadoc:
更新消息属性。对于updateMessage的调用会被合并,稍后在FX应用程序线程上运行,因此即使从FX应用程序线程调用updateMessage,也可能不会立即更新此属性,并且中间的消息值可以合并以节省事件通知。
该方法可以安全地从任何线程调用。
Task
javadoc中有许多使用updateMessage()
的示例。