JavaFX进度指示器未正确更新

时间:2018-02-15 12:16:47

标签: java javafx

我正在创建一个JavaFX桌面应用程序,我正在模拟一些工作负载。我希望应用程序有一个动态更新的进度指示器(当前时间过去),以显示加载过程的进展情况。这是我的应用程序类:

public class App extends Application {

@Override
public void init() throws InterruptedException{
    //Simulation of time consuming code.
    for(int i = 0; i<=10; i++) {
        notifyPreloader(new Preloader.ProgressNotification(i/10));
        System.out.println("Progress is being set by the app to: " + (i/10));
        Thread.sleep(500);
    }
}

@Override
public void start(Stage primaryStage) {
    Parent root;
    try {
        root = FXMLLoader.load(getClass().getResource("/gui/fxml/App.fxml"));
        Scene scene = new Scene(root, 600, 400);

        scene.getStylesheets().add("/gui/style/app.css");

        primaryStage.setScene(scene);
        primaryStage.setTitle("Hello World!");
        primaryStage.show();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
}

这是我的预加载器类:

public class AppPreloader extends Preloader {
private Stage preloaderStage;
private Parent root;
private Scene scene;
private ProgressIndicator progress_indicator;

@Override
public void start(Stage primaryStage) throws Exception {
    this.preloaderStage = primaryStage;
    this.preloaderStage.setScene(this.scene);
    this.preloaderStage.show();
    this.progress_indicator = (ProgressIndicator) scene.lookup("#progressIndicator");
}


@Override
public void init() throws Exception {
    root = FXMLLoader.load(getClass().getResource("/gui/fxml/AppPreloader.fxml"));
    Platform.runLater(new Runnable() { 
        @Override
        public void run() {
            scene = new Scene(root, 600, 400);
            scene.getStylesheets().add("/gui/style/appPreloader.css");
        }
    });
}

@Override
public void handleProgressNotification(ProgressNotification pn) {
    if(pn instanceof ProgressNotification){
        progress_indicator.setProgress(pn.getProgress());
        System.out.println("Progress is being set by the handle method to: " + pn.getProgress());
    }
}

@Override
public void handleStateChangeNotification(StateChangeNotification evt) {
    if (evt.getType() == StateChangeNotification.Type.BEFORE_START) {
        preloaderStage.hide();
    }
}    
}
打印句子我已经能够识别出两个问题:第一, 在App类的handleProgressNotification方法的循环开始之前,init方法被调用两次,一次被设置为0而另一个被设置为1。 谁在打电话?我该如何避免呢?

第二个问题是app类init方法中的打印句子总是打印0.0。 怎么可能呢?这是并发问题吗?

此外,我需要说我已经检查了这两个问题(progressbar in preloader does not updatejavafx preloader not updating progress),但没有找到解决问题的方法。

非常感谢你的时间。

1 个答案:

答案 0 :(得分:1)

首先,由于您使用的是整数算术,因此您没有看到预期的进度值:i10都是整数,因此i/10为{{1} } 0时的0 <= i < 101。{/ p>

其次,i=10handleProgressNotification方法是与加载资源相关的应用程序生命周期的一部分。这些都是JavaFX仍然支持Web部署并且现在可能使用有限的时代的遗留物。

要从应用程序接收通知,您需要覆盖handleStateChangeNotification方法。以下是两个类的更正版本(也可以单独修改,以便可以复制和运行:请在您的问题中提供这些示例):

handleApplicationNotification(...)
package application;

import javafx.application.Application;
import javafx.application.Preloader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class App extends Application {

    @Override
    public void init() throws InterruptedException{
        //Simulation of time consuming code.
        for(int i = 0; i<=10; i++) {
            notifyPreloader(new Preloader.ProgressNotification(i/10.0));
            System.out.println("Progress is being set by the app to: " + (i/10.0));
            Thread.sleep(500);
        }
        notifyPreloader(new Preloader.StateChangeNotification(Preloader.StateChangeNotification.Type.BEFORE_START));
    }

    @Override
    public void start(Stage primaryStage) {
        Parent root;
            root = new StackPane(new Label("Hello World"));
            Scene scene = new Scene(root, 600, 400);

            primaryStage.setScene(scene);
            primaryStage.setTitle("Hello World!");
            primaryStage.show();

    }

}