Multithreading 观察家赢得';t在JavaFXGUI中运行更新

Multithreading 观察家赢得';t在JavaFXGUI中运行更新,multithreading,javafx,observers,Multithreading,Javafx,Observers,我读了很多关于javafxgui模型、Plattform->RunLater和线程的内容,但我仍然不知道如何正确地实现这一点。我有一个JavaFXGUI,它通过点击按钮执行一个过程并更新进度条和标签。这在线程和平台上运行得很好,但我不得不将其更改为观察者模型 我在单例模型中调用了一个进度跟踪器,它由执行流程的类更新,并且是可观察的。我还实现了一个Observer,它应该更新两个UI元素 带有按钮事件的GUI控制器 private void createKeyPressed(ActionEvent

我读了很多关于javafxgui模型、
Plattform->RunLater
和线程的内容,但我仍然不知道如何正确地实现这一点。我有一个JavaFXGUI,它通过点击按钮执行一个过程并更新进度条和标签。这在线程和平台上运行得很好,但我不得不将其更改为观察者模型

我在单例模型中调用了一个进度跟踪器,它由执行流程的类更新,并且是可观察的。我还实现了一个Observer,它应该更新两个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();

}
公共静态void createKey(字符串长度){
任务;
任务=新任务(){
@凌驾
public Void call()引发异常{
initTracker(0,“开始”);
doStuff();
ProgressTracker.getTracker().setTracker(1,“第一”);
doStuff();
ProgressTracker.getTracker().setTracker(2,“秒”);
//等等
返回null;
}
};
新线程(任务)
.start();
}
ProgressTracker中的打印将被执行。但是,如果我在Observer的更新中添加打印,则不会打印任何内容。如果我在Progresstracker中进行检查,则观察者计数为1

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

不要重新发明轮子。这是可观察模式的现成实现:不需要自己实现。此外,
Task
已经定义了更新各种属性的方法,这些属性可以从任何线程调用,但将在FX应用程序线程上安排实际更新。例如,请参见和

因此,您可以这样做,例如:

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 ;

}
公共静态任务createKey(字符串长度){
任务;
任务=新任务(){
最终整数总步数=;
@凌驾
public Void call()引发异常{
updateProgress(0,totalSteps);
更新消息(“开始”);
doStuff();
updateProgress(1,totalSteps);
更新消息(“第一”);
doStuff();
updateProgress(2,totalSteps);
更新消息(“第二条”);
//等等
返回null;
}
};
新线程(任务)
.start();
返回任务;
}

private void createKeyPressed(ActionEvent事件){
//使进度条可见
pbKeyProgress.visibleProperty().set(true);
如果(!Check.keyFileExistant()| | cbKeyOverwrite.selectedProperty().get()){
Task Task=Creator.createKey(cbKeyLength.getValue());
pbKeyProgress.progressProperty().bind(task.progressProperty());
lblKeyProgress.textProperty().bind(task.messageProperty());
}否则{
}
}

我建议您阅读这篇文章。线程看起来都是正确的。可能错误在代码中的其他地方(如果您无法找到它,请尝试创建一个)。不过,您实际上是在重新发明轮子:是Observer模式的现成实现,使用起来比编写自己的实现方便得多。您还可以调用任务的
updateProgress()
updateMessage()
方法,然后将进度条和标签绑定到任务的相应属性。这似乎很有趣,但我必须尝试并完全理解它,然后才能标记您的答案。一个问题是,创建者必须为CLI和GUI工作,我想使用ProgressTracker来统一状态更新,并有两个不同的观察者,一个用于CLI,一个用于GUI。我将检查这个带有Propertys的模型是否适用于这两种模式,并将其标记为正确。但是已经谢谢你的帮助了@chenino以一种合理的方式考虑需要重用的代码应该是相当简单的。如前所述,我将对此进行验证,然后将其标记为正确。谢谢:)(不知怎的,@James\u D没有空格被删除了)
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 {
    }
}