【发布时间】:2019-12-22 18:20:48
【问题描述】:
我一直在使用 javafx 开发机器人模拟器。它使用一个单独的线程来计算机器人及其每个部件在每次增量后应该在哪里。 UI 的实际更新是通过调用Platform.runLater() 来处理的。
这是一个名为 leftFinger 的节点(在本例中为 Rectangle)如何被操作的示例:
首先,在 Controller 类中,创建一个 Translate 对象并将其添加到节点的变换中:
leftFingerTranslateTransform = new Translate(0, 0);
leftFinger.getTransforms().add(leftFingerTranslateTransform);
然后,在传递给Platform.runLater() 的方法中执行以下操作:
leftFingerTranslateTransform.setY(-40.0 * (armScale - 1.0));
leftFingerTranslateTransform.setX(fingerPos);
上面的效果很好。
有一次,我不小心将一些节点重新定位代码(即对 Tranlate.setX() 和 Translate.setY() 的调用)放入了一个由非 UI 线程调用的方法中,而没有调用 @987654328 @。令我惊讶的是,这行得通,没有任何问题。但我想知道这是否会引起问题。
我对 javafx 和多线程信息的搜索使我相信 UI 不能(或至少不应该)直接从非 UI 线程进行操作。通过实验,我发现尝试从非 UI 线程向场景添加节点会导致抛出异常,但操作(即更改属性)属于节点的变换不会。
我的问题是:属于节点的转换是否可以安全地从非 UI 线程更改其属性(不使用 Platform.runLater())?
【问题讨论】:
-
“……我想知道这是否会导致问题。”是的。线程问题因不会立即引起明显问题而臭名昭著,但最终肯定会导致问题。
-
"节点对象可以在任何线程上构建和修改,只要它们尚未附加到正在显示的窗口中的场景。应用程序必须将节点附加到这样的场景或修改它们在 JavaFX 应用程序线程上" –
Node。这条规则没有例外,尽管有些对象限制性更强,只能在 FX 线程上构造或修改(例如Stage)。 -
Group的边界取决于子元素的变换。因此,对转换的更新可能会触发布局传递。我没有调查,如果这会导致问题,但我的可能性很高......
标签: java multithreading javafx