簡體   English   中英

JavaFX 進度指示器未正確更新

[英]JavaFX Progress Indicator not updating properly

我正在創建一個 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 類的init方法的循環開始之前, handleProgressNotification方法被調用了兩次,一次被設置為 0,其他被設置為 1 . 誰在打電話? 我怎樣才能避免它?

第二個問題是app類的init方法里面的print語句總是打印0.0.0。 這怎么可能? 是並發問題嗎?

另外我需要說我已經檢查了這兩個問題( preloader 中的 progressbar 沒有更新javafx preloader 沒有更新 progress )並且沒有找到我的問題的解決方案。

非常感謝您的時間。

首先,您沒有看到預期的進度值,因為您使用的是整數運算: i10都是整數,因此i/100表示0 <= i < 101i=10

其次, handleProgressNotificationhandleStateChangeNotification方法是與加載資源相關的應用程序生命周期的一部分。 這些確實是 JavaFX 仍然支持 Web 部署的時代遺留下來的,現在可能用途有限。

要從應用程序接收通知,您需要重寫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();

    }

}
package application;

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

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 {
        progress_indicator = new ProgressIndicator();
        root = new StackPane(progress_indicator);
        scene = new Scene(root, 600, 400);
        this.preloaderStage = primaryStage;
        this.preloaderStage.setScene(this.scene);
        this.preloaderStage.show();
    }


    @Override
    public void handleApplicationNotification(PreloaderNotification pn) {
        if (pn instanceof ProgressNotification) {
           //expect application to send us progress notifications 
           //with progress ranging from 0 to 1.0
           double v = ((ProgressNotification) pn).getProgress();
           progress_indicator.setProgress(v);            
        } else if (pn instanceof StateChangeNotification) {
            StateChangeNotification scn = (StateChangeNotification) pn ;
            if (scn.getType() == StateChangeNotification.Type.BEFORE_START) {
                preloaderStage.hide();
            }
        }
    } 
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM