Всплывающее окно, предназначенное для отображения ProgressBar, не отображается в JavaFX - PullRequest
2 голосов
/ 06 августа 2020

Я хочу отобразить ProgressBar с помощью Popup в JavaFX, чтобы я мог заставить ProgressBar исчезнуть, вызвав метод PopUp s hide(). Однако вместо того, чтобы исчезнуть после завершения фоновой задачи, ProgessBar вообще не отображается.

import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.scene.Scene;
import javafx.scene.control.ProgressBar;
import javafx.scene.layout.StackPane;
import javafx.stage.Popup;
import javafx.stage.Stage;

public class Main extends Application {

    @Override
    public void start(Stage stage) {
        StackPane root = new StackPane();

        Popup popup = new Popup();
        ProgressBar bar = new ProgressBar();
        popup.getContent().add(bar);

        Task<Void> task = new Task<>() {
            @Override
            protected Void call() {
                for (int i = 0; i < 100; i++) {
                    try {
                        Thread.sleep(100);
                        updateProgress(i, 100);
                    } catch (Exception ignored) {
                    }
                }
                return null;
            }
        };

        bar.progressProperty().bind(task.progressProperty());
        task.setOnSucceeded(workerStateEvent -> popup.hide());
        popup.show(stage);
        new Thread(task).start();

        stage.setScene(new Scene(root, 100, 100));
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Когда я запускаю приведенный выше код, все, что я вижу, это пустая стадия, показанная здесь: Пустая сцена вместо ProgressBar

Если я добавлю ProgressBar к Stage вручную с помощью root.getChildren().add(bar), полоса отобразится правильно, а progressProperty будет правильно привязан, поэтому я знаю, что проблема связана с Popup. Однако при использовании этого метода полоса не исчезает после завершения фоновой задачи.

1 Ответ

3 голосов
/ 06 августа 2020

Я нигде не могу найти это задокументировано, но я думаю, что владелец Popup должен отображаться, чтобы метод Popup.show(owner) был успешным. Таким образом, следующее переупорядочение вашего кода (вызов stage.show() перед popup.show(stage)) работает:

@Override
public void start(Stage stage) {
    StackPane root = new StackPane();

    Popup popup = new Popup();
    ProgressBar bar = new ProgressBar();
    popup.getContent().add(bar);

    Task<Void> task = new Task<>() {
        @Override
        protected Void call() {
            for (int i = 0; i < 100; i++) {
                try {
                    Thread.sleep(100);
                    updateProgress(i, 100);
                } catch (Exception ignored) {
                }
            }
            return null;
        }
    };

    bar.progressProperty().bind(task.progressProperty());
    task.setOnSucceeded(workerStateEvent -> popup.hide());

    stage.setScene(new Scene(root, 100, 100));
    stage.show();
    
    popup.show(stage);
    new Thread(task).start();

}

Обратите внимание, что ваш другой подход работает: вам просто нужно удалить индикатор выполнения с графика сцены, когда задача полный:

    @Override
    public void start(Stage stage) {
        StackPane root = new StackPane();

//        Popup popup = new Popup();
        
        ProgressBar bar = new ProgressBar();
//        popup.getContent().add(bar);
        root.getChildren().add(bar);

        Task<Void> task = new Task<>() {
            @Override
            protected Void call() {
                for (int i = 0; i < 100; i++) {
                    try {
                        Thread.sleep(100);
                        updateProgress(i, 100);
                    } catch (Exception ignored) {
                    }
                }
                return null;
            }
        };

        bar.progressProperty().bind(task.progressProperty());
//        task.setOnSucceeded(workerStateEvent -> popup.hide());
        task.setOnSucceeded(event -> root.getChildren().remove(bar));

        stage.setScene(new Scene(root, 100, 100));
        stage.show();

        
//        popup.show(stage);
        new Thread(task).start();

    }
...