活动场景图中 JavaFX 节点的所有操作都必须在 JavaFX 应用程序线程上运行,否则您的程序可能无法正常工作。
JavaFX 将抛出异常IllegalStateException: Not on FX application thread
当您尝试在 JavaFX 应用程序线程之外修改场景图节点的属性时。即使您没有收到 IllegalStateException,您也不应该在 JavaFX 应用程序线程之外修改场景图节点,因为如果您这样做,您的代码可能会意外失败。
Using Platform.runLater()
将操作场景图节点的代码包装在平台.runLater https://openjfx.io/javadoc/17/javafx.graphics/javafx/application/Platform.html#runLater(java.lang.Runnable)调用以允许 JavaFX 系统在 JavaFX 应用程序线程上运行代码。
例如,您可以使用以下代码修复示例程序:
Platform.runLater(() -> label.setText(""));
替代方案使用Task
with a message
财产
如果您使用的是 JavaFXTask https://openjfx.io/javadoc/17/javafx.graphics/javafx/concurrent/Task.html,它对使用 JavaFX 的并发编程有一些内置支持,那么您可以利用它的优势message https://openjfx.io/javadoc/17/javafx.graphics/javafx/concurrent/Task.html#updateMessage(java.lang.String)属性,可以从任何线程安全地更新,但只会在 JavaFX 线程上中继属性更改。
这是一个示例(来自任务 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 https://openjfx.io/javadoc/17/javafx.graphics/javafx/concurrent/Task.html#updateMessage(java.lang.String)javadoc:
更新消息属性。对 updateMessage 的调用被合并并且
稍后在 FX 应用程序线程上运行,因此调用 updateMessage,
即使来自 FX 应用程序线程,也不一定会导致
立即更新此属性和中间消息值
可以合并以节省事件通知。
这个方法是安全的
从任何线程调用。
有很多使用的例子updateMessage()
in the Task
javadoc。