在 JavaFX 中显示带进度条的弹出窗口

问题描述 投票:0回答:3

如何通过弹出窗口显示进度条并在进程完成后自动关闭。这是我的代码。

 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(),显示弹出窗口需要手动退出才能关闭弹出窗口,但显示进度条。

对此有什么想法/想法吗?

javafx popup progress-bar
3个回答
22
投票

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

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

2
投票

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


0
投票

Bonjour vous pouvez utiliser,马尔凯 `公共类 Chargement 实现了可初始化 { @FXML 公共进度指示器 Myprogessbar;

     @FXML
        public AnchorPane changer;
     @FXML
        private Label label;

    
    public void initialize(URL arg0, ResourceBundle arg1) {
        
         try {
                //  animation qui fait passer la valeur du ProgressIndicator de 0 à 1 en une seconde
                Timeline timeline = new Timeline();
                timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(5), new KeyValue(Myprogessbar.progressProperty(), 1)));
                timeline.setCycleCount(1);

                timeline.play();
                timeline.setOnFinished(new EventHandler<ActionEvent>() {

                    @Override
                    public void handle(ActionEvent arg0) {
                    
                        label.setText(" ");
                        Stage stage = new Stage();
                        changer.getScene().getWindow().hide();
                        
                }
                });
                } catch (Exception e) {
                    e.printStackTrace();
                    }
         

} } `

} }

您在经典中的应用程序

© www.soinside.com 2019 - 2024. All rights reserved.