为了账号安全,请及时绑定邮箱和手机立即绑定

从JavaFX中的不同线程更新UI

从JavaFX中的不同线程更新UI

当年话下 2019-12-27 10:15:30
我正在开发一个具有几个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的建议设法做到了。为了解决后端必须等待控制台打印的问题,我实现了一种缓冲的控制台。它将要打印的字符串存储在中,StringBuffer并TextArea在flush()调用方法时将它们实际附加到。我使用AtomicBoolean来防止在刷新完成之前发生下一代操作,因为刷新是由Platform.runLater()可运行的操作完成的。另请注意,此解决方案的速度非常慢。
查看完整描述

2 回答

?
忽然笑

TA贡献1806条经验 获得超5个赞

执行此操作的最佳方法是使用TaskJavaFx。到目前为止,这是我在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();


查看完整回答
反对 回复 2019-12-27
  • 2 回答
  • 0 关注
  • 1340 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信