JavaFX 警报对话框忽略焦点按钮

JavaFX alert dialog ignores the focused button

为什么 JavaFX 警告对话框会触发 Platform.exit();当我按下 Enter 键时,即使警报对话框中的焦点按钮是取消?

soaStage.setOnCloseRequest(new EventHandler<WindowEvent>() 
{
    @Override
    public void handle(WindowEvent event) 
    {
        Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
        alert.setTitle("Confirm");
        alert.setHeaderText("Are you sure you want to exit?");
        alert.setContentText("Press OK to exit, or Cancel to stay.");
        alert.initOwner(soaStage);

        Optional<ButtonType> result = alert.showAndWait();
        if (result.get() == ButtonType.OK)
        {
            Platform.exit();
        } 
        else 
        {
            event.consume();
        }
    }
});

默认按钮在 enter

时触发

当您按下 enter 时会触发确定按钮,因为它是 default button.

A default Button is the button that receives a keyboard VK_ENTER press, if no other node in the scene consumes it.

在默认的 JavaFX 8 Modena 样式表中,默认按钮用蓝色表示,而不是标准按钮的灰色。

如何删除默认按钮行为

您可以通过不将“确定”按钮设为默认按钮来从警告对话框中删除此行为:

Button okButton = (Button) alert.getDialogPane().lookupButton(ButtonType.OK);
okButton.setDefaultButton(false);

我建议您不要这样做,而是始终在警报对话框中保留一个默认按钮。

在 OS X 上,标准警报类型对话框有一个默认按钮,它由 enter 触发,即使另一个按钮被聚焦,所以 JavaFX 中的标准行为是与此一致。注意:要在 OS X 的默认对话框中允许此行为,必须 enable full keyboard access.

如果您确实将“确定”按钮更改为不是默认按钮,我建议您将其文本更改为其他内容(例如,退出您的案例):

okButton.setText("Exit");

如何制作 enter 聚焦按钮

现在,如果您还想在按下 enter 时触发焦点按钮,那么您可以这样做:

EventHandler<KeyEvent> fireOnEnter = event -> {
    if (KeyCode.ENTER.equals(event.getCode()) 
            && event.getTarget() instanceof Button) {
        ((Button) event.getTarget()).fire();
    }
};

DialogPane dialogPane = alert.getDialogPane();
dialogPane.getButtonTypes().stream()
        .map(dialogPane::lookupButton)
        .forEach(button ->
                button.addEventHandler(
                        KeyEvent.KEY_PRESSED,
                        fireOnEnter
                )
        );

注意:在任何情况下,当您按下 space.

时,焦点按钮总是被激活

我们可以通过创建需要在应用程序启动时实例化一次的 class 将 ENTER 绑定添加到整个按钮。

public class EnableButtonEnterKey extends ButtonBehavior<Button> {
    public EnableButtonEnterKey() {
        super(new Button());
        BUTTON_BINDINGS.add(new KeyBinding(ENTER, KEY_PRESSED, "Press"));
        BUTTON_BINDINGS.add(new KeyBinding(ENTER, KEY_RELEASED, "Release"));
    }
}

启动应用程序时,调用

new EnableButtonEnterKey();

就是这样。