【问题标题】:JavaFX alert dialog ignores the focused buttonJavaFX 警报对话框忽略焦点按钮
【发布时间】:2015-04-30 05:19:18
【问题描述】:

为什么 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();
        }
    }
});

【问题讨论】:

  • 我相信要激活焦点按钮,您必须按空格键。这是真的(我认为)不仅适用于 Java/JavaFX。例如,在 Windows 原生提示中,我使用 tab 来快速导航并使用空格来激活所选按钮,而不是 Enter。这是根据我的经验,我不知道这是否是一个既定的指导方针。
  • 我猜你是对的,但我只是在 C# 中尝试了 MessageBoxButtons.YesNo,我们可以通过 Enter 键或空格键激活焦点按钮。
  • 我明白了。我的评论更多是个人观点,不管它值多少钱。将其读作“,作为用户,按空格键激活焦点按钮,而不是回车”。

标签: javafx alert


【解决方案1】:

默认按钮在 enter

时触发

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

如果场景中没有其他节点使用它,则默认按钮是接收键盘 VK_ENTER 按下的按钮。

在默认的 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 时,始终会触发焦点按钮。

【讨论】:

    【解决方案2】:

    我们可以通过创建一个需要在应用程序启动时实例化一次的类来为整个按钮添加 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();
    

    就是这样。

    【讨论】:

      猜你喜欢
      • 2015-06-14
      • 2015-08-27
      • 1970-01-01
      • 2015-06-26
      • 2012-01-03
      • 1970-01-01
      • 2010-12-20
      • 2019-03-20
      • 1970-01-01
      相关资源
      最近更新 更多