我正在尝试为大学项目构建交通模拟。 已经实现了交通灯逻辑,动态控制所有交通灯等...... 我坚持添加车辆作为路径过渡节点。 如果我添加很多它们,每个都有自己的boundsInParentProperty更改监听器:
-与其他车辆碰撞以使它们分开
-交通灯前的区域,红灯亮时可以 parking
然后我会进行大量计算,这将使动画不流畅,应用程序变得无响应。
我猜测转换需要成为主 javafx ui 线程的一部分,那么监听器呢? 感谢任何有关选择正确方法的帮助
最佳答案
线程的规则是:
- 作为场景图一部分的节点的任何属性都必须是 由 FX 应用程序线程访问。
- 避免在 FX 应用程序线程上进行任何不必要的计算。
显然,您所处的情况很难管理,因为冗长的计算涉及必须在 FX 应用程序线程上访问的属性。
javafx.concurrent 包和 javafx.animation 包有许多工具可以简化线程管理。具体来说,有许多回调定义了在 FX 应用程序线程上执行的区域。
节点修改其属性,并因此在 FX 应用程序线程上执行任何更改监听器的方法。转换会更新它们在 FX 应用程序线程上操作的属性的状态,并对 setOnFinished(...)
等回调执行相同的操作。在javafx.concurrent API中,Task
类有一个call(...)
方法,该方法旨在在后台线程上执行,并且有各种回调方法(updateMessage(...)
, updateProgress(...)
),以及一些处理程序:setOnSucceeded(...)
等,全部在 FX 应用程序线程上执行。
对于这样的模拟,我建议查看 AnimationTimer 。它有一个 handle()
方法供您实现,该方法为每个渲染帧调用一次。它接收一个 long
参数,该参数是以纳秒为单位的时间戳。 JavaFX 的目标帧速率(当前)为 60fps,因此您应该瞄准此处执行速度相当快的代码,否则您会降低帧速率,但实际上您可以在 16ms 内完成很多工作。
Here是使用此技术的一个示例。这只是模拟了很多球在盒子里弹跳,但它会给你一个想法。我还有一个版本,其中每个球都实现了自己的AnimationTimer来检查墙壁碰撞,然后还有另一个AnimationTimer来检查球与球的碰撞;性能几乎相同(这并不奇怪)。我还在未完成的《太空入侵者》模拟中使用了“每个对象的动画帧”方法,效果非常好。
关于JavaFX 流量模拟转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23094605/