javafx.scene.control.Dialog won't close on

2019-01-26 14:27发布

If I just create an empty class extending from javafx.scene.control.Dialog<R>, it won't close when I'm pressing the "x" button in the top right corner.

How do I implement this behaviour? The API seems to tell me that I need to implement a close button. But in my case I don't want a close button, I just want to close the window with the x button or by pressing ESC. Is this possible?

4条回答
爱情/是我丢掉的垃圾
2楼-- · 2019-01-26 15:06

To quote the Api Docs:

JavaFX dialogs can only be closed 'abnormally' (as defined above) in two situations:

  1. When the dialog only has one button, or

  2. When the dialog has multiple buttons, as long as one of them meets one of the following requirements:

    1. The button has a ButtonType whose ButtonData is of type ButtonData.CANCEL_CLOSE.
    2. The button has a ButtonType whose ButtonData returns true when ButtonData.isCancelButton() is called.

    ...

So either add at least one button or multiple buttons, and one of them is of type ButtonData.CANCEL_CLOSE, for example:

Dialog<ButtonType> dialog = new Dialog<>();
dialog.getDialogPane().getButtonTypes().add(new ButtonType("Got it!", ButtonData.CANCEL_CLOSE));
dialog.setContentText("test");
dialog.showAndWait();

Edit:

This behavior is implemented in javafx.scene.control.FXDialog.requestPermissionToClose(Dialog<?>), but the real FXDialog shown is HeavyweightDialog which is not public API so not really an extension point.

查看更多
我欲成王,谁敢阻挡
3楼-- · 2019-01-26 15:15

The workaround from @eckig or @jewelsea works pretty fine. But I would use something like this:

// Somewhere in code
Dialog<?> dialog = new Dialog<>();
Window    window = dialog.getDialogPane().getScene().getWindow();
window.setOnCloseRequest(event -> window.hide());

I do not know any constrains of this use, but it worked for me. And I recommend initialize window right after dialog initialization, like above.

查看更多
我想做一个坏孩纸
4楼-- · 2019-01-26 15:22

To work-around this, you could add a hidden close button to the dialog.

import javafx.application.Application;
import javafx.scene.*;
import javafx.scene.control.*;
import javafx.stage.Stage;

public class DialogClosure extends Application{

    @Override
    public void start(Stage stage) throws Exception {
        Button openDialog = new Button("Open Dialog");
        openDialog.setOnAction(event -> {
            Dialog dialog = new Dialog();
            dialog.getDialogPane().getButtonTypes().add(ButtonType.CLOSE);
            Node closeButton = dialog.getDialogPane().lookupButton(ButtonType.CLOSE);
            closeButton.managedProperty().bind(closeButton.visibleProperty());
            closeButton.setVisible(false);
            dialog.showAndWait();
        });

        stage.setScene(new Scene(openDialog));
        stage.show();
    }
    public static void main(String[] args) {
        launch(args);
    }
}

Then the dialog meets both your requirement of being able to be closed via the native windowing system's window close icon as well as the JavaFX Dialog requirement of including a close button in the dialog for the close icon to work.

Alternately, you could use a Stage with showAndWait instead of a Dialog. A Stage without any included buttons is closable using the windowing system's close window icon.

查看更多
兄弟一词,经得起流年.
5楼-- · 2019-01-26 15:24

In my Dialog<ButtonType> I'm using what @vbargl said:

Window window = alert.getDialogPane().getScene().getWindow();
window.setOnCloseRequest(event -> window.hide());

It closes the dialog, but it's bringing me a no value present error.

To avoid it, I'm also checking result.get() and that result.isPresent().

查看更多
登录 后发表回答