观察者不会在JavaFX GUI中运行更新

时间:2017-03-29 14:00:27

标签: multithreading javafx observers

我读了很多关于JavaFX GUI模型,Plattform->RunLater和线程,但我仍然不知道如何做到这一点。我有一个JavaFX GUI,点击按钮执行一个过程并更新了Progres Bar和Label。这与Threading和Plattform运行良好,但我不得不将其更改为观察者模型。 我在Singleton模型中调用Progress Tracker,由执行该过程的类更新并且是Observable。我实现了一个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());
        });

    }

}

Progress Tracker

    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中的Print将被执行。但是,如果我在Observer的更新中添加一个打印件,则不会打印任何内容。如果我在Progresstracker中检查,观察者计数是1。 为什么即使调用Notify,Observer也不会得到通知或执行任何操作?我的线程和执行模式是否错误? 进度条和标签也将保持其初始值

1 个答案:

答案 0 :(得分: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 {
    }
}