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

如何在处理数据时正确更新 JavaFX GUI

如何在处理数据时正确更新 JavaFX GUI

当年话下 2023-06-04 17:09:39
我正在尝试进入 JavaFX 以首次尝试使用 Java 制作 GUI。因此,我制作了一个简单的神经网络来学习 XOR 并在 JavaFX 中显示输出。我的问题是 - 如何在处理数据时定期更新 GUI?到目前为止,我所取得的一切都是网络完成学习后 GUI 中的一次更新。即使我在线程中启动了网络。我希望 GUI 的右侧更新(圆圈根据输出改变颜色)定期为每个 n 纪元而不是一次。附图显示了网络启动前的 GUI。
查看完整描述

1 回答

?
湖上湖

TA贡献2003条经验 获得超2个赞

JavaFX 有一个“事件线程”,负责处理按钮点击、更新标签和任何其他与 GUI 相关的任务。当您调用时button.setOnAction(e -> doSomething());,当您按下按钮时,doSomething()发生在 JavaFX 线程上。在此运行期间,不会发生其他 GUI 事件。这意味着您的界面将完全冻结,从而导致糟糕的用户体验。


此外,您不能在 JavaFX 线程以外的任何线程上执行 GUI 操作,否则您将获得一个IllegalStateException. (试着打电话Executors.newSingleThreadExecutor().execute(() -> label.setText("hello"));看看这个在行动)


幸运的是,JavaFX 提供了解决这个问题的方法。


首先,也是最简单的方法,是在新线程中调用长时间运行的方法(可能使用ExecutorService上面的 s),当您需要修改接口时,将这些调用包装在对Platform.runLater(() -> updateInterface());. 这将发布updateInterface()到 GUI 线程,并允许它运行。


但是,这可能会很麻烦,因此首选方法是使用Service.


假设您的长时间运行的计算返回一个Double,您创建一个类 extending Service<Double>,覆盖它的createTask()方法,并在那里执行计算,如下所示:


public class CalculationService extends Service<Double> {

    @Override

    protected Task<Double> createTask() {

        return new Task<Double>() {

            @Override

            protected Double call() throws Exception {

                return doCalculation();

            }

        };

    }

}

然后,在你的控制器中,声明一个private final CalculationService service = new CalculationService();


在您的控制器initialize()方法中,您可以将此服务的输出绑定到您想要的任何内容。例如:


calculationDisplayLabel.textProperty().bind(Bindings.createStringBinding(service.valueProperty()));

// continuously updates the label whenever the service calculates a new value

然后,每当您决定要重新开始计算时,service.restart()如果进程正在运行,您可以调用中断进程,并从头开始。


如果要在值更改时调用代码,请向服务的值添加一个侦听器。例如,如果您希望它在完成后立即重新计算,请调用:


service.valueProperty().addListener((obs, old, newValue) -> service.restart());

查看完整回答
反对 回复 2023-06-04
  • 1 回答
  • 0 关注
  • 90 浏览

添加回答

举报

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