Сцена скрыта, когда отображается диалоговое окно

У меня есть этот код, который отображает диалоговое окно подтверждения для выхода из приложения.

    public class DialogPanels
{

    public void initClosemainAppDialog(final Stage primaryStage)
    {

        primaryStage.setOnCloseRequest(new EventHandler<WindowEvent>()
        {
            @Override
            public void handle(WindowEvent event)
            {
                event.consume(); // Do nothing on close request

                // Dialog Stage init
                final Stage dialog = new Stage();
                dialog.initModality(Modality.APPLICATION_MODAL);

                // Frage - Label
                Label label = new Label("Exit from the program");


                // Button "Yes"
                Button okBtn = new Button("Yes");
                okBtn.setOnAction(new EventHandler<ActionEvent>()
                {
                    @Override
                    public void handle(ActionEvent event)
                    {
                        //primaryStage.close();  
                        //dialog.close();
                        //Platform.exit();     
                        System.exit(0);
                    }
                });

                // Button "No"
                Button cancelBtn = new Button("No");
                cancelBtn.setOnAction(new EventHandler<ActionEvent>()
                {
                    @Override
                    public void handle(ActionEvent event)
                    {
                        primaryStage.show();
                        dialog.close();
                    }
                });

                // Layout for the Button
                HBox hbox = new HBox();
                hbox.setSpacing(10);
                hbox.setAlignment(Pos.CENTER);
                hbox.getChildren().add(okBtn);
                hbox.getChildren().add(cancelBtn);

                // Layout for the Label and hBox
                VBox vbox = new VBox();
                vbox.setAlignment(Pos.CENTER);
                vbox.setSpacing(10);
                vbox.getChildren().add(label);
                vbox.getChildren().add(hbox);

                // Stage
                Scene scene = new Scene(vbox);
                dialog.setScene(scene);
                dialog.show();
            }
        });

    }
}

Проблема в том, что при закрытии основного приложения отображается диалоговое окно, а основная сцена скрыта. Я хочу отобразить диалоговое окно перед основной сценой. Можете ли вы помочь мне исправить это?

ОБНОВЛЕНИЕ

Я протестировал этот код, он работает, но когда отображается диалоговое окно, основная сцена не несет ответственности (заморожена). Как я могу сделать главную сцену ответственной, когда я отображаю диалог?


person Peter Penzov    schedule 06.06.2013    source источник


Ответы (2)


Используйте событие закрытия и установите владельца сцены, если вы не хотите видеть другое окно, когда окна свернуты:

@Override
public void handle(WindowEvent event)
{
    event.consume(); // Do nothing on close request

    // Dialog Stage init
    final Stage dialog = new Stage();
    dialog.initModality(Modality.APPLICATION_MODAL);
    dialog.initOwner(primaryStage);

    // other stuff
}
});
person Uluk Biy    schedule 06.06.2013
comment
Да, это решает проблему. Еще один вопрос. Когда отображается диалоговое окно, основная сцена зависает (не несет ответственности за ожидание диалога), как я могу отобразить диалоговое окно, а также позволить основной сцене работать? - person Peter Penzov; 06.06.2013
comment
dialog.initModality(Modality.NONE) - person Uluk Biy; 06.06.2013
comment
Я изменил Modality на NONE, но теперь основная сцена закрывается, когда я отображаю диалоговое окно (назад в начале). - person Peter Penzov; 06.06.2013
comment
@ПитерПензов. Основная сцена в моем случае не закрыта. Какую версию JavaFX вы используете? - person Uluk Biy; 06.06.2013
comment
@PeterPenzov Я тестировал 2.2.21-b11, и он работает, как и ожидалось, на моей 64-битной машине с Windows 7. - person Uluk Biy; 06.06.2013

Вам необходимо установить правильные отношения между primaryStage и диалоговым этапом. Вот подсказка, чтобы вы начали:

...
dialog.initOwner(primaryStage);
dialog.initModality(Modality.APPLICATION_MODAL);
dialog.showAndWait();

Дополнительную информацию можно найти в JavaFX 2 JavaDocs от Oracle.

Еще пример кода (редактировать)

Я использую setOnHiding(..) вместо setOnCloseRequest(..):

stage.setOnHiding(new AskUserIfHeReallyWantsToQuitWindowHandler(stage));

Я извлек ваш код в отдельный класс обработчика событий и исправил упомянутые мной проблемы (извините, сейчас у меня мало времени):

public class AskUserIfHeReallyWantsToQuitWindowHandler implements EventHandler<WindowEvent> {
    private final Stage primaryStage;

    public AskUserIfHeReallyWantsToQuitWindowHandler(final Stage primaryStage) {
                    Objects.requireNonNull(primaryStage);
        this.primaryStage = primaryStage;
    }

    @Override
    public void handle(final WindowEvent event) {

        event.consume();

        final Stage dialog = new Stage();

        final Button okBtn = new Button("Yes");
        okBtn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(final ActionEvent event) {
                dialog.close();
                primaryStage.close();
            }
        });

        // Button "No"
        final Button cancelBtn = new Button("No");
        cancelBtn.setOnAction(new EventHandler<ActionEvent>() {
            @Override
            public void handle(final ActionEvent event) {
                dialog.close();

                Platform.runLater(new Runnable() {

                    @Override
                    public void run() {
                        primaryStage.show();
                    }
                });
            }
        });

        // Layout for the Button
        final HBox hbox = new HBox();
        hbox.setSpacing(10);
        hbox.setAlignment(Pos.CENTER);
        hbox.getChildren().add(okBtn);
        hbox.getChildren().add(cancelBtn);

        // Layout for the Label and hBox
        final VBox vbox = new VBox();
        vbox.setAlignment(Pos.CENTER);
        vbox.setSpacing(10);
        vbox.getChildren().add(new Label("Do your really want to exit?"));
        vbox.getChildren().add(hbox);

        // Stage
        final Scene scene = new Scene(vbox);
        dialog.setScene(scene);
        dialog.initOwner(primaryStage);
        dialog.initModality(Modality.NONE);

        dialog.showAndWait();
    }
}
person Jens Birger Hahn    schedule 06.06.2013
comment
Я пытаюсь помочь вам с закрытием основного этапа. В вашем коде есть над чем работать (например, использовать Platform.exit()), использовать событие и так далее. Что точно не работает должным образом? - person Jens Birger Hahn; 06.06.2013
comment
Диалог отображается за основной сценой. - person Peter Penzov; 06.06.2013
comment
Можете ли вы опубликовать больше кода и какую платформу и версию JavaFX 2 вы точно используете? Обработка окон в Linux выглядит нормально. - person Jens Birger Hahn; 06.06.2013
comment
Я использую последнюю версию JavaFX. Это полный исходный код: pastebin.com/6KQJ5QfN - person Peter Penzov; 06.06.2013
comment
В вашем коде вызываются как showAndWait(), так и show(). Я собираюсь отредактировать свой пост с большим количеством кода, который работает для меня... - person Jens Birger Hahn; 06.06.2013
comment
Очень странно, вы называете это событие кодом AskUserIfHeReallyWantsToQuitWindowHandler dialog = new AskUserIfHeReallyWantsToQuitWindowHandler(primaryStage);? Верный? Когда я закрываю основную сцену, диалоговое окно не отображается. Программа просто нормально закрывается. - person Peter Penzov; 06.06.2013
comment
Как следует из названия, это не диалог, а WindowHandler. Можете ли вы снова вставить свой код? - person Jens Birger Hahn; 06.06.2013
comment
Вы забыли добавить EventHandler к primaryStage в методе start(..) вашего приложения, поэтому диалоговое окно не отображается: primaryStage = setOnHiding(new DialogPanels(primaryStage)); Если у вас все еще есть проблема, продолжайте вставлять код :-). - person Jens Birger Hahn; 06.06.2013
comment
Да, я получаю ожидаемый результат, но заметил небольшую проблему. Когда я нажимаю кнопку No в диалоговом окне, бэкстейдж перезагружается. Это нормально или этого можно избежать? - person Peter Penzov; 06.06.2013
comment
Возможно перезагрузка экрана вызвана setOnHiding. Могу ли я заменить его чем-то другим? - person Peter Penzov; 06.06.2013
comment
Это ошибка в JVM 7 javafx-jira.kenai.com/browse/RT-24879. Он отлично работает на JVM 8. - person Peter Penzov; 06.06.2013
comment
Интересно - так что я был недалек от того, чтобы назвать JavaFX немного пронизанным ошибками :-)! - person Jens Birger Hahn; 07.06.2013