【问题标题】:Observer won't run update in JavaFX GUI观察者不会在 JavaFX GUI 中运行更新
【发布时间】:2021-02-17 03:45:55
【问题描述】:

我阅读了很多关于 JavaFX GUI 模型、Plattform->RunLater 和线程的信息,但我仍然不知道如何正确处理。我有一个 JavaFX GUI,单击按钮即可执行进程并更新进度条和标签。这在线程和平台上运行良好,但我不得不将其更改为观察者模型。

我在单例模型中调用进度跟踪器,该模型由执行流程的类更新并且是可观察的。我还实现了一个观察者,它应该更新两个 UI 元素。

带有按钮事件的 GUI 控制器

private void createKeyPressed(ActionEvent event) {

    // Make Progressbar visible
    pbKeyProgress.visibleProperty().set(true);

    if (!Check.keyFileExistant() || cbKeyOverwrite.selectedProperty().get()) {
        ProgressTracker.getTracker().addObserver(new ProgressObserver(pbKeyProgress, lblKeyProgress));
        Creator.createKey(cbKeyLength.getValue());
    } else {
    }
}

进度观察者

public class ProgressObserver implements Observer {

    private final ProgressBar progressBar;
    private final Label statusLabel;

    public ProgressObserver(ProgressBar progressBar, Label statusLabel) {

        this.progressBar = progressBar;
        this.statusLabel = statusLabel;
    }

    @Override

    public void update(Observable o, Object o1) {
        Platform.runLater(() -> {
            System.out.println("Tracker set to "+ProgressTracker.getProgress() + " " + ProgressTracker.getStatus());
            progressBar.setProgress(ProgressTracker.getProgress());
            statusLabel.setText(ProgressTracker.getStatus());
        });

    }

}

进度跟踪器

    public synchronized void setTracker(int currentStep, String currentStatus) {

    checkInstance();
    instance.step = currentStep;
    instance.status = currentStatus;
    instance.notifyObservers();
    System.out.println(instance.countObservers());
}

创作者

public static void createKey(String length) {

    Task<Void> task;
    task = new Task<Void>() {
        @Override
        public Void call() throws Exception {
            initTracker(0,"Start");
            doStuff();
            ProgressTracker.getTracker().setTracker(1,"First");
            doStuff();
            ProgressTracker.getTracker().setTracker(2,"Second");
            // and so on

            return null;

        }
    };

    new Thread(task)
            .start();

}

ProgressTracker 中的打印被执行。但是,如果我在 Observer 的更新中添加打印,则不会打印任何内容。如果我在 Progresstracker 中检查,观察者计数为 1。

为什么 Observer 没有得到通知或执行任何操作,即使 Notify 被调用?我把线程和执行模型弄错了吗? 进度条和标签也将保持其初始值。

【问题讨论】:

  • 我推荐你阅读that的文章。
  • 线程看起来都正确。错误可能在您的代码中的其他地方(如果您无法弄清楚,请尝试创建minimal reproducible example)。不过,您实际上是在重新发明轮子:JavaFX properties pattern 是观察者模式的现成实现,使用起来比编写自己的实现要方便得多。您也可以调用任务的updateProgress()updateMessage()方法,然后只需将进度条和标签绑定到任务的相应属性即可。

标签: multithreading javafx observers


【解决方案1】:

不要重新发明轮子。 JavaFX Properties Pattern 是 Observable 模式的现成实现:无需自己实现。此外,Task 已经定义了用于更新各种属性的方法,可以从任何线程调用这些方法,但会在 FX 应用程序线程上安排实际更新。例如,请参阅 updateProgress()updateMessage()

所以你可以这样做,例如:

public static Task<Void> createKey(String length) {

    Task<Void> task;
    task = new Task<Void>() {

        final int totalSteps = ... ;
        @Override
        public Void call() throws Exception {
            updateProgress(0, totalSteps);
            updateMessage("Start");
            doStuff();
            updateProgress(1, totalSteps);
            updateMessage("First");
            doStuff();
            updateProgress(2, totalSteps);
            updateMessage("Second");
            // and so on

            return null;

        }
    };

    new Thread(task)
            .start();

    return task ;

}

private void createKeyPressed(ActionEvent event) {

    // Make Progressbar visible
    pbKeyProgress.visibleProperty().set(true);

    if (!Check.keyFileExistant() || cbKeyOverwrite.selectedProperty().get()) {
        Task<Void> task = Creator.createKey(cbKeyLength.getValue());
        pbKeyProgress.progressProperty().bind(task.progressProperty());
        lblKeyProgress.textProperty().bind(task.messageProperty());
    } else {
    }
}

【讨论】:

  • 嗯,这看起来很有趣,但我必须尝试完全理解它才能标记您的答案。一个问题是,创建者必须为 CLI 和 GUI 工作,我想使用 ProgressTracker 来统一状态更新并有 2 个不同的观察者,一个用于 CLI,一个用于 GUI。我将检查这个带有属性的模型是否适用于这两种模式,以及是否将其标记为正确。但是已经谢谢你的帮助了!
  • @chenino 以合理的方式分解出需要可重用的代码应该相当简单。
  • 是的,在我看来是这样的。如前所述,我将验证这一点并将其标记为正确。谢谢 :) (不知何故 @James_D 没有空间被删除)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-11-01
  • 1970-01-01
  • 1970-01-01
  • 2016-02-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多