从JavaFX中的不同线程更新UI



0 Answers

执行此操作的最佳方法是在JavaFx中使用Task 。 到目前为止,这是我在JavaFx中更新UI控件时遇到的最好的技术。

Task task = new Task<Void>() {
    @Override public Void run() {
        static final int max = 1000000;
        for (int i=1; i<=max; i++) {
            updateProgress(i, max);
        }
        return null;
    }
};
ProgressBar bar = new ProgressBar();
bar.progressProperty().bind(task.progressProperty());
new Thread(task).start();
Question

我正在开发一个具有多个TextField对象的应用程序,这些对象需要更新以反映相关后端属性的更改。 TextField不可编辑,只有后端可能会更改其内容。

据我所知,正确的方法是在单独的线程上运行繁重的计算,以免阻塞UI。 我使用javafx.concurrent.Task做了这个,并使用updateMessage()将单个值传回给JavaFX线程,这很有效。 但是,我需要更新多个值,因为后端会进行其处理。

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

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

我在这里找到了一些问题:

转换为UI的记录器条目不再随时间更新

JavaFX中的多线程挂起了UI

但我的问题仍然存在。

总结:我有一个后端对属性进行更改,我希望这些更改出现在GUI上。 后端是遗传算法,因此其操作被分解为离散的世代。 我想要的是TextField在代之间至少刷新一次,即使这会延迟下一代。 更重要的是,GUI响应良好,而GA运行速度快。

如果我没有明确问题,我可以发布一些代码示例。

UPDATE

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




Related