在 JavaFX 中使用 ProgressBar 显示弹出窗口
Display Popup with ProgressBar in JavaFX
如何通过弹出窗口显示我的进度条并在进程完成后自动关闭。这是我的代码。
Task<ProgressForm> task = new Task<ProgressForm>() {
@Override
public ProgressForm call() throws InterruptedException{
ProgressForm pf = new ProgressForm();
for (int i = 1; i <= 10; i++) {
pf.activateProgressBar(this);
updateProgress(i, 10);
}
return pf;
}
};
task.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(WorkerStateEvent t) {
ProgressForm pf = (ProgressForm)task.getValue();
pf.getDialogStage().close();
}
});
Thread th = new Thread(task);
th.run();
进度表class:
private final Stage dialogStage;
private final ProgressBar pb = new ProgressBar();
private final ProgressIndicator pin = new ProgressIndicator();
public ProgressForm() {
dialogStage = new Stage();
dialogStage.initStyle(StageStyle.UTILITY);
dialogStage.setResizable(false);
dialogStage.initModality(Modality.APPLICATION_MODAL);
// PROGRESS BAR
final Label label = new Label();
label.setText("alerto");
pb.setProgress(-1F);
pin.setProgress(-1F);
final HBox hb = new HBox();
hb.setSpacing(5);
hb.setAlignment(Pos.CENTER);
hb.getChildren().addAll(pb, pin);
Scene scene = new Scene(hb);
dialogStage.setScene(scene);
}
public void activateProgressBar(final Task task) throws InterruptedException {
pb.progressProperty().bind(task.progressProperty());
pin.progressProperty().bind(task.progressProperty());
dialogStage.show();
}
public Stage getDialogStage() {
return dialogStage;
}
这段代码的问题是
- 如果我使用 .show(),显示弹出窗口很流畅,但没有进度条。
- 如果我使用 .showAndWait(),显示弹出窗口需要手动退出以关闭弹出窗口但进度条显示。
对此有任何thoughts/ideas吗?
JavaFX 中多线程的两条规则是:
- 修改 UI 的代码(创建
Stage
或更改属性
作为场景图一部分的节点)必须在
JavaFX 应用程序线程。违反此规则将抛出
IllegalStateException
s 或导致不可预测的行为。
- 需要很长时间执行的代码应该在后台线程中执行(即不是 FX 应用程序线程)。违反此规则将导致 UI 无响应。
您的代码违反了第一条规则,因为它在后台线程中调用了 ProgressForm
构造函数。您应该先设置 UI,显示对话框,然后启动后台线程。
注意,不需要重复绑定进度条和指示器的progress
属性到任务的progress
属性。一旦绑定,它将一直保持绑定状态,除非您解除绑定。
很难按原样修复您的代码,因为您的后台任务实际上并不执行任何需要花费时间的事情。这是您正在执行的操作的一个版本:
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class ProgressDialogExample extends Application {
@Override
public void start(Stage primaryStage) {
Button startButton = new Button("Start");
startButton.setOnAction(e -> {
ProgressForm pForm = new ProgressForm();
// In real life this task would do something useful and return
// some meaningful result:
Task<Void> task = new Task<Void>() {
@Override
public Void call() throws InterruptedException {
for (int i = 0; i < 10; i++) {
updateProgress(i, 10);
Thread.sleep(200);
}
updateProgress(10, 10);
return null ;
}
};
// binds progress of progress bars to progress of task:
pForm.activateProgressBar(task);
// in real life this method would get the result of the task
// and update the UI based on its value:
task.setOnSucceeded(event -> {
pForm.getDialogStage().close();
startButton.setDisable(false);
});
startButton.setDisable(true);
pForm.getDialogStage().show();
Thread thread = new Thread(task);
thread.start();
});
StackPane root = new StackPane(startButton);
Scene scene = new Scene(root, 350, 75);
primaryStage.setScene(scene);
primaryStage.show();
}
public static class ProgressForm {
private final Stage dialogStage;
private final ProgressBar pb = new ProgressBar();
private final ProgressIndicator pin = new ProgressIndicator();
public ProgressForm() {
dialogStage = new Stage();
dialogStage.initStyle(StageStyle.UTILITY);
dialogStage.setResizable(false);
dialogStage.initModality(Modality.APPLICATION_MODAL);
// PROGRESS BAR
final Label label = new Label();
label.setText("alerto");
pb.setProgress(-1F);
pin.setProgress(-1F);
final HBox hb = new HBox();
hb.setSpacing(5);
hb.setAlignment(Pos.CENTER);
hb.getChildren().addAll(pb, pin);
Scene scene = new Scene(hb);
dialogStage.setScene(scene);
}
public void activateProgressBar(final Task<?> task) {
pb.progressProperty().bind(task.progressProperty());
pin.progressProperty().bind(task.progressProperty());
dialogStage.show();
}
public Stage getDialogStage() {
return dialogStage;
}
}
public static void main(String[] args) {
launch(args);
}
}
您可以使用 controlsfx 库轻松显示此
private void progressDialogue(){
copyWorker = createWorker();
ProgressDialog dialog = new ProgressDialog(copyWorker);
dialog.initStyle(StageStyle.TRANSPARENT);
dialog.setGraphic(null);
//stage.initStyle(StageStyle.TRANSPARENT);
dialog.initStyle(StageStyle.TRANSPARENT);
//dialog.setContentText("Files are Uploading");
//dialog.setTitle("Files Uploading");
//dialog.setHeaderText("This is demo");
dialog.setHeaderText(null);
dialog.setGraphic(null);
dialog.initStyle(StageStyle.UTILITY);
new Thread(copyWorker).start();
dialog.showAndWait();
}
public Task createWorker() {
return new Task() {
@Override
protected Object call() throws Exception {
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
updateMessage("2000 milliseconds");
updateProgress(i + 1, 10);
}
return true;
}
};
}
现在您需要调用方法 progressDialogue();
如何通过弹出窗口显示我的进度条并在进程完成后自动关闭。这是我的代码。
Task<ProgressForm> task = new Task<ProgressForm>() {
@Override
public ProgressForm call() throws InterruptedException{
ProgressForm pf = new ProgressForm();
for (int i = 1; i <= 10; i++) {
pf.activateProgressBar(this);
updateProgress(i, 10);
}
return pf;
}
};
task.setOnSucceeded(new EventHandler<WorkerStateEvent>() {
@Override
public void handle(WorkerStateEvent t) {
ProgressForm pf = (ProgressForm)task.getValue();
pf.getDialogStage().close();
}
});
Thread th = new Thread(task);
th.run();
进度表class:
private final Stage dialogStage;
private final ProgressBar pb = new ProgressBar();
private final ProgressIndicator pin = new ProgressIndicator();
public ProgressForm() {
dialogStage = new Stage();
dialogStage.initStyle(StageStyle.UTILITY);
dialogStage.setResizable(false);
dialogStage.initModality(Modality.APPLICATION_MODAL);
// PROGRESS BAR
final Label label = new Label();
label.setText("alerto");
pb.setProgress(-1F);
pin.setProgress(-1F);
final HBox hb = new HBox();
hb.setSpacing(5);
hb.setAlignment(Pos.CENTER);
hb.getChildren().addAll(pb, pin);
Scene scene = new Scene(hb);
dialogStage.setScene(scene);
}
public void activateProgressBar(final Task task) throws InterruptedException {
pb.progressProperty().bind(task.progressProperty());
pin.progressProperty().bind(task.progressProperty());
dialogStage.show();
}
public Stage getDialogStage() {
return dialogStage;
}
这段代码的问题是
- 如果我使用 .show(),显示弹出窗口很流畅,但没有进度条。
- 如果我使用 .showAndWait(),显示弹出窗口需要手动退出以关闭弹出窗口但进度条显示。
对此有任何thoughts/ideas吗?
JavaFX 中多线程的两条规则是:
- 修改 UI 的代码(创建
Stage
或更改属性 作为场景图一部分的节点)必须在 JavaFX 应用程序线程。违反此规则将抛出IllegalStateException
s 或导致不可预测的行为。 - 需要很长时间执行的代码应该在后台线程中执行(即不是 FX 应用程序线程)。违反此规则将导致 UI 无响应。
您的代码违反了第一条规则,因为它在后台线程中调用了 ProgressForm
构造函数。您应该先设置 UI,显示对话框,然后启动后台线程。
注意,不需要重复绑定进度条和指示器的progress
属性到任务的progress
属性。一旦绑定,它将一直保持绑定状态,除非您解除绑定。
很难按原样修复您的代码,因为您的后台任务实际上并不执行任何需要花费时间的事情。这是您正在执行的操作的一个版本:
import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.ProgressBar;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.HBox;
import javafx.scene.layout.StackPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
public class ProgressDialogExample extends Application {
@Override
public void start(Stage primaryStage) {
Button startButton = new Button("Start");
startButton.setOnAction(e -> {
ProgressForm pForm = new ProgressForm();
// In real life this task would do something useful and return
// some meaningful result:
Task<Void> task = new Task<Void>() {
@Override
public Void call() throws InterruptedException {
for (int i = 0; i < 10; i++) {
updateProgress(i, 10);
Thread.sleep(200);
}
updateProgress(10, 10);
return null ;
}
};
// binds progress of progress bars to progress of task:
pForm.activateProgressBar(task);
// in real life this method would get the result of the task
// and update the UI based on its value:
task.setOnSucceeded(event -> {
pForm.getDialogStage().close();
startButton.setDisable(false);
});
startButton.setDisable(true);
pForm.getDialogStage().show();
Thread thread = new Thread(task);
thread.start();
});
StackPane root = new StackPane(startButton);
Scene scene = new Scene(root, 350, 75);
primaryStage.setScene(scene);
primaryStage.show();
}
public static class ProgressForm {
private final Stage dialogStage;
private final ProgressBar pb = new ProgressBar();
private final ProgressIndicator pin = new ProgressIndicator();
public ProgressForm() {
dialogStage = new Stage();
dialogStage.initStyle(StageStyle.UTILITY);
dialogStage.setResizable(false);
dialogStage.initModality(Modality.APPLICATION_MODAL);
// PROGRESS BAR
final Label label = new Label();
label.setText("alerto");
pb.setProgress(-1F);
pin.setProgress(-1F);
final HBox hb = new HBox();
hb.setSpacing(5);
hb.setAlignment(Pos.CENTER);
hb.getChildren().addAll(pb, pin);
Scene scene = new Scene(hb);
dialogStage.setScene(scene);
}
public void activateProgressBar(final Task<?> task) {
pb.progressProperty().bind(task.progressProperty());
pin.progressProperty().bind(task.progressProperty());
dialogStage.show();
}
public Stage getDialogStage() {
return dialogStage;
}
}
public static void main(String[] args) {
launch(args);
}
}
您可以使用 controlsfx 库轻松显示此
private void progressDialogue(){
copyWorker = createWorker();
ProgressDialog dialog = new ProgressDialog(copyWorker);
dialog.initStyle(StageStyle.TRANSPARENT);
dialog.setGraphic(null);
//stage.initStyle(StageStyle.TRANSPARENT);
dialog.initStyle(StageStyle.TRANSPARENT);
//dialog.setContentText("Files are Uploading");
//dialog.setTitle("Files Uploading");
//dialog.setHeaderText("This is demo");
dialog.setHeaderText(null);
dialog.setGraphic(null);
dialog.initStyle(StageStyle.UTILITY);
new Thread(copyWorker).start();
dialog.showAndWait();
}
public Task createWorker() {
return new Task() {
@Override
protected Object call() throws Exception {
for (int i = 0; i < 10; i++) {
Thread.sleep(100);
updateMessage("2000 milliseconds");
updateProgress(i + 1, 10);
}
return true;
}
};
}
现在您需要调用方法 progressDialogue();