[英]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 )并且没有找到我的问题的解决方案。
非常感谢您的时间。
首先,您没有看到预期的进度值,因为您使用的是整数运算: i
和10
都是整数,因此i/10
为0
表示0 <= i < 10
和1
当i=10
。
其次, handleProgressNotification
和handleStateChangeNotification
方法是与加载资源相关的应用程序生命周期的一部分。 这些确实是 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.