从JavaFX中的不同线程更新UI

我正在开发一个具有几个TextField对象的应用程序,这些对象需要进行更新以反映关联的后端属性中的更改。该TextFields为不可编辑,只有后端可能会改变他们的内容。

据我了解,正确的方法是在单独的线程上运行大量计算,以免阻塞UI。我使用javafx.concurrent.Task进行了此操作,并使用updateMessage()很好地将单个值传递回了JavaFX线程。但是,我需要多个值来更新,因为后端需要处理。

由于后端值存储为JavaFX属性,因此我尝试将它们简单地绑定到textProperty每个GUI元素的,然后让绑定完成工作。但是,这不起作用。在运行了片刻之后,TextField即使后端任务仍在运行,s也会停止更新。没有例外。

我还尝试使用Platform.runLater()来主动更新TextFields而不是绑定。这里的问题runLater()是计划任务的速度比平台运行任务的速度快,因此GUI变得迟钝,即使后端任务完成后,GUI也需要时间来“赶上”。

但我的问题仍然存在。

总结:我有一个对属性进行更改的后端,并且我希望这些更改出现在GUI上。后端是一种遗传算法,因此其操作可分为几代。我希望TextFields在两代之间至少刷新一次,即使这会延迟下一代。与GA快速运行相比,GUI的良好响应更为重要。

如果我还没有解决这个问题,我可以发布一些代码示例。

更新

我按照James_D的建议设法做到了。为了解决后端必须等待控制台打印的问题,我实现了一种缓冲的控制台。它将要打印的字符串存储在中,StringBufferTextAreaflush()调用方法时将它们实际附加到。我使用AtomicBoolean来防止在刷新完成之前发生下一代操作,因为刷新是由Platform.runLater()可运行的操作完成的。另请注意,此解决方案的速度非常慢。


当年话下
浏览 1341回答 2
2回答

忽然笑

执行此操作的最佳方法是使用TaskJavaFx。到目前为止,这是我在JavaFx中更新UI控件时遇到的最好的技术。Task task = new Task<Void>() {&nbsp; &nbsp; @Override public Void run() {&nbsp; &nbsp; &nbsp; &nbsp; static final int max = 1000000;&nbsp; &nbsp; &nbsp; &nbsp; for (int i=1; i<=max; i++) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; updateProgress(i, max);&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; return null;&nbsp; &nbsp; }};ProgressBar bar = new ProgressBar();bar.progressProperty().bind(task.progressProperty());new Thread(task).start();
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java