在应用程序FX线程之外是否有放宽JavaFX属性更新规则的计划?

时间:2017-10-16 20:45:34

标签: javafx-8

我有一个有效的JavaFX应用程序。它有三个主要部分:

  1. 整个应用程序全局可见的信号列表。每个信号都有一个可观察的String值属性。在构造JavaFX场景之前实例化该列表,信号列表构造函数在Application FX线程中运行。

  2. 作为Observable Array List实现的JavaFX表,以便在信号值发生变化时,它们会在GUI上自动更新。

  3. 运行循环以改变信号值的模拟引擎。此循环在工作线程中运行。

  4. 我完全清楚选择列表,文本框等GUI元素只能在Application FX线程中更新。我使用Platform.runLater(someRunnableThing)来做到这一点。然而,让我蒙羞的是,即使更改信号值(更改可观察的String属性的值),也必须在FX线程中完成,否则将在应用程序-TF内线程异常中抛出异常。

    奇怪的是,尽管有这些例外情况,应用程序仍能正常工作,因为最终(瞬间向人类观察者)拾取并显示更改的值。在发布之前对运行时行为进行最终检查时,我才注意到这一点。

    当GUI根据变化的变量显示信息时,工作线程在后台更改变量是很常见的事情。 Platform.runLater()价格昂贵且有些不确定。由于工作线程没有触及GUI,并且应用程序FX线程可以选择在任何时候获取更新,因为Java强制这种行为对我来说似乎很苛刻。

    我是否错过了修改观察到的属性的内容?任何想法和想法都赞赏。

1 个答案:

答案 0 :(得分:1)

没有关于从后台线程更新JavaFX属性的规则。唯一的规则是,您无法从后台线程更新属于场景图的节点,并且没有计划(可能永远不会)放宽该规则。

您没有发布任何代码,因此我们只能对实际问题做出有根据的猜测。可能发生的情况是,您在后台线程中更改了其中一个属性(或可观察集合)的侦听器或绑定,其中侦听器/绑定正在更新UI。具有observables的监听器(包括由绑定创建和注册的监听器)当然是在更改observable的同一线程上调用的。

所以,如果你有像

这样的东西
someApplicationProperty.addListener((obs, oldValue, newValue) -> {
    someUIElement.setSomeValue(...);
});

或者

someUIElement.someProperty().bind(someApplicationProperty);

只需用

替换它
someApplicationProperty.addListener((obs, oldValue, newValue) -> {
    Platform.runLater(() -> someUIElement.setSomeValue(...));
});

换句话说,只要您的侦听器从FX应用程序线程更新UI,您就可以继续从后台线程更新应用程序属性。

在UI组件本身注册侦听器的情况下,必须确保在UI线程上更改了用于注册侦听器的observable。您提到的示例中就是这种情况,例如更新ListViewTableView的支持列表。您可以通过直接调用Platform.runLater()或在模型和UI之间放置一个图层来完成此操作。对于后一种方法,请参阅Correct Way to update Observable List from background thread

也许可以看http://www.oracle.com/technetwork/articles/java/javafxinteg-2062777.html