Display popups with ProgressBar in JavaFX

How can I display a progress bar through a popup and automatically close if the process is complete. Here is my code.

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

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

Problem with this code

  • If I use .show (), the popup window display is smooth, but without the PROGRESS BAR.
  • if I use .showAndWait (), displaying pop-ups requires a manual exit to pop up before closing. While a progress bar is displayed.

Any thoughts / ideas on this?

+6
source share
1 answer

Two rules for multithreading in JavaFX:

  • Code that modifies the user interface (creates a Stage or changes the properties of nodes that are part of the scene graphics) must be run on the JavaFX Application Theme. Violation of this rule will either throw an IllegalStateException or lead to unpredictable behavior.
  • Code that takes a long time to execute must be executed in the background thread (i.e. not in the FX application thread). Violation of this rule will cause the user interface to become unresponsive.

Your code violates the first rule because it calls the ProgressForm constructor in the background thread. You must first set up the user interface, show the dialog, and then start the background thread.

Note that there is no need to relink the progress properties of the progress bar and indicator to the progress property of the task. Once he is bound, he will remain bound until you untie him.

It is very difficult to fix your code, since your background task does not actually do anything that is required at any time. Here's a version of what you are doing, just a pause:

 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); } } 
+14
source

Source: https://habr.com/ru/post/985111/


All Articles