首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何从我自己的线程中安全地修改JavaFX GUI节点?

如何从我自己的线程中安全地修改JavaFX GUI节点?
EN

Stack Overflow用户
提问于 2013-11-13 04:39:26
回答 1查看 3.6K关注 0票数 6

我试图更改线程中的JavaFX图形用户界面节点,但我看到以下错误:

线程" Thread-8“java.lang.IllegalStateException中的异常:不在FX应用程序线程上;currentThread =Thread-8

生成错误的示例代码:

代码语言:javascript
复制
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
    }
  }
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 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应用程序线程上运行代码。

例如,可以使用以下代码修复示例程序:

代码语言:javascript
复制
Platform.runLater(() -> label.setText(""));

使用带有Task message 属性的的替代方案

如果您使用的是JavaFX 任务,它对使用JavaFX的并发编程有一些内置的支持,那么您可以利用它的消息属性,它可以从任何线程中安全地更新,但只会在JavaFX线程上中继属性更改。

下面是一个示例(来自Task javadoc):

代码语言:javascript
复制
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中反映不断变化的消息值:

代码语言:javascript
复制
Label iterationLabel = new Label();
iterationLabel.textProperty().bind(
    task.messageProperty()
);

updateMessage javadoc:

更新消息属性。对updateMessage的调用在FX应用程序线程上合并并运行,因此对updateMessage的调用,即使是来自notifications线程的调用,也不一定会导致对该属性的立即更新,中间消息值可能合并在一起以保存事件通知。 从任何线程调用此方法都是安全的。

updateMessage() javadoc中有许多使用Task的例子。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19945422

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档