我试图更改线程中的JavaFX图形用户界面节点,但我看到以下错误:
线程" Thread-8“java.lang.IllegalStateException中的异常:不在FX应用程序线程上;currentThread =Thread-8
生成错误的示例代码:
public class Controller {
public Label label = new Label();
public void load() {
MyThread myThread = new MyThread();
myThread.start();
}
public class MyThread extends Thread {
public void run() {
......
label.setText(""); // IllegalStateException: Not on FX application thread
}
}
}发布于 2013-11-13 05:00:25
在活动场景图中对JavaFX节点的所有操作都必须在JavaFX应用程序线程上运行,否则程序可能无法正常工作。
当您试图从JavaFX应用程序线程中修改场景图节点的属性时,IllegalStateException: Not on FX application thread将抛出异常IllegalStateException: Not on FX application thread。即使您没有得到一个IllegalStateException,您也不应该修改JavaFX应用程序线程中的场景图节点,因为如果您这样做了,您的代码可能会无法预料地失败。
使用Platform.runLater()的
包装代码,它在Platform.runLater调用中操纵场景图节点,以允许JavaFX系统在JavaFX应用程序线程上运行代码。
例如,可以使用以下代码修复示例程序:
Platform.runLater(() -> label.setText(""));使用带有Task message 属性的的替代方案
如果您使用的是JavaFX 任务,它对使用JavaFX的并发编程有一些内置的支持,那么您可以利用它的消息属性,它可以从任何线程中安全地更新,但只会在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;
}
}; 然后,您可以安全地绑定到message属性,以便在UI中反映不断变化的消息值:
Label iterationLabel = new Label();
iterationLabel.textProperty().bind(
task.messageProperty()
);updateMessage javadoc:
更新消息属性。对updateMessage的调用在FX应用程序线程上合并并运行,因此对updateMessage的调用,即使是来自notifications线程的调用,也不一定会导致对该属性的立即更新,中间消息值可能合并在一起以保存事件通知。 从任何线程调用此方法都是安全的。
在updateMessage() javadoc中有许多使用Task的例子。
https://stackoverflow.com/questions/19945422
复制相似问题