我的软件有一个按钮,里面有一个很重的onAction ActionEvent。 我正在尝试使用自定义任务更新此 ActionEvent 内的进度栏。 但进度条仅在 ActionEvent 完全结束后才会更新。
由于我的软件是一个大型项目(~8000行),我会尝试尽可能地总结代码:
这是我的自定义任务:
public class VolumeProgressTask extends Task<Double> {
@Setter private Volume volume;
@Override
protected Double call() {
double actualProgress = this.volume.getWindow().getLeftArea().getSeriesTab().getActualProgress();
double progress = 0;
double newProgress;
double newActualProgress = 0;
do {
newProgress = this.volume.getReader().getProgress();
if (newProgress != progress) {
progress = newProgress;
newActualProgress = actualProgress + (progress * this.volume.getLayers().size());
updateProgress(newActualProgress, this.volume.getWindow().getLeftArea().getSeriesTab().getMaxProgress());
double percent = newActualProgress / this.volume.getWindow().getLeftArea().getSeriesTab().getMaxProgress();
System.out.println("percent: " + percent + " ,actual progress: " + this.volume.getWindow().getLeftArea().getSeriesTab().getProgressBar().getProgress());
}
} while (newProgress < 1);
this.volume.getWindow().getLeftArea().getSeriesTab().setActualProgress(newActualProgress);
return newActualProgress;
}
}
我已经确保控制台在任务中打印正确的百分比。
此任务在软件开始时在名为“窗口”的对象内启动。 ProgressBar 绑定也在这里完成
@Getter @Setter private VolumeProgressTask volumeProgressTask = new VolumeProgressTask();
this.leftArea.getSeriesTab().getProgressBar().progressProperty().bind(this.volumeProgressTask.progressProperty());
这是我所说的按钮触发的ActionEvent:
EventHandler<ActionEvent> openFolderClickAction = (event) -> {
try {
String dicomSeriesFolderPath = LocalLoaderUtils.selectFolder(this.window.getStage());
new Volume(dicomSeriesFolderPath, this.window);
} catch (Exception e) {
throw new RuntimeException(e);
}
};
Volume 类的相关部分:
this.window.getVolumeProgressTask().setVolume(this);
Thread progressTaskThread = new Thread(this.window.getVolumeProgressTask());
progressTaskThread.setDaemon(true);
progressTaskThread.start();
progressTaskThread.join();
最后是包含 ProgressBar 的 SeriesTab 类:
@Getter private final ProgressBar progressBar = new ProgressBar();
@Getter @Setter private double actualProgress;
@Getter @Setter private double maxProgress;
我消耗了大量示例、教程视频和 stackOverflow 问题,但没有成功。感谢您阅读本文。
这是一个最小的可重现示例:
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressBar;
import javafx.stage.Stage;
import lombok.Getter;
@Getter
public class MRE extends Application {
private ProgressBar progressBar;
private Button btn;
private double count = 0;
private final long max = 1000000;
public static void main (String[] args) {
Application.launch();
}
@Override
public void start (Stage primaryStage) {
Stage stage = new Stage();
Group group = new Group();
Scene scene = new Scene(group);
stage.initOwner(primaryStage);
stage.setWidth(120);
stage.setHeight(120);
stage.setTitle("minimal reproducible example");
stage.setScene(scene);
stage.show();
this.btn = new Button();
this.btn.setPrefHeight(25);
this.btn.setPrefWidth(100);
this.btn.setTranslateX(10);
this.btn.setTranslateY(10);
this.btn.setOnAction(event -> {
btnAction(this);
this.count = 0;
});
this.btn.setText("run actionEvent");
group.getChildren().add(this.btn);
this.progressBar = new ProgressBar();
this.progressBar.setTranslateX(10);
this.progressBar.setTranslateY(45);
this.progressBar.setPrefHeight(25);
this.progressBar.setPrefWidth(100);
group.getChildren().add(this.progressBar);
}
public void btnAction (MRE MREObj) {
TestTask task = new TestTask(this);
MREObj.getProgressBar().progressProperty().bind(task.progressProperty());
Thread taskThread = new Thread(task);
taskThread.setDaemon(true);
taskThread.start();
for (int i = 1; i <= this.max; i++) {
System.out.println("hi");
this.count++;
}
}
}
class TestTask extends Task<Void> {
private final MRE MREObj;
public TestTask (MRE MREObj) {
this.MREObj = MREObj;
}
@Override
protected Void call () {
double actualProgress = 0;
double newProgress;
do {
newProgress = this.MREObj.getCount();
if (newProgress != actualProgress) {
actualProgress = newProgress;
updateProgress(actualProgress, this.MREObj.getMax());
System.out.println("progress: " + (actualProgress/this.MREObj.getMax()));
}
} while(this.MREObj.getCount() < this.MREObj.getMax());
updateProgress(this.MREObj.getMax(), this.MREObj.getMax());
return null;
}
}