gpt4 book ai didi

JavaFX 进度指示器未正确更新

转载 作者:行者123 更新时间:2023-11-30 06:17:51 30 4
gpt4 key购买 nike

我正在创建一个 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方法中的打印语句总是打印0.0。 这怎么可能?是并发问题吗?

此外,我需要说的是,我已经检查了这两个问题( progressbar in preloader does not updatejavafx preloader not updating 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();
}
}
}
}

关于JavaFX 进度指示器未正确更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48807095/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com