在JavaFX中使用ProgressBar显示弹出窗口

时间:2015-04-14 10:35:51

标签: javafx popup progress-bar

如何通过弹出显示我的进度条,如果进程完成则自动关闭。这是我的代码。

 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();

进度表类:

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;
}

此代码的问题是

  1. 如果我使用.show(),显示弹出窗口是顺畅但没有进度条。
  2. 如果我使用.showAndWait(),显示弹出窗口需要手动退出以弹出关闭但是显示进度条。
  3. 关于此的任何想法/想法?

2 个答案:

答案 0 :(得分:18)

JavaFX中的多线程的两个规则是:

  1. 修改UI的代码(创建Stage或更改属性 作为场景图的一部分的节点)必须才能执行 JavaFX应用程序线程。违反此规则将抛出 IllegalStateException或导致不可预测的行为。
  2. 执行需要很长时间的代码应在后台线程中执行(即不是FX应用程序线程)。违反此规则将导致UI无响应。
  3. 您的代码违反了第一条规则,因为它在后台线程中调用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);
        }
    }
    

答案 1 :(得分:0)

您可以使用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();

代码来自此视频:https://www.youtube.com/watch?v=DK_1YGLI9ig