首页 文章

使用JavaFX中的Enter键触发按钮的onAction

提问于
浏览
11

我是JavaFx的新手 . 在我的JavaFX应用程序中,我设置了onAction属性,当我使用鼠标按下按钮时,它工作正常 . 即使用户按下Enter按钮,我也要发射相同的内容 . 我知道我可以使用偶数处理程序来做到这一点 . 但是当我阅读onAction JavaDoc时,它说这个事件会被按键发生 .

属性描述:按钮的动作,每当按钮被触发时都会调用它 . 这可能是由于用户使用鼠标单击按钮,或通过触摸事件或按键,或者开发人员以编程方式调用fire()方法 .

但是当我按下Enter键时没有任何反应 . 这是文档中的错误吗?如果不在按钮上添加alistener,还有其他方法可以实现吗?

P.S

在评论后我用空格键检查然后它被解雇了 . 但我想将其设置为Enter键 . 我有很多按钮 . 我试过 button.setDefaultButton(true); 但它没有被解雇 . 我认为这是因为有多个按钮 . 如果我只将它设置为一个按钮,它可以正常工作 . 如何设置多个按钮?

3 回答

  • 0

    您可以使用绑定动态更改当前聚焦按钮的默认按钮属性

    btn.defaultButtonProperty().bind(btn.focusedProperty());
    
  • 0

    如果要将其应用于程序中的每个Button,可以将JavaFX-Button子类化并在构造函数中绑定它 . 在您的fxml-File中,您需要包含自定义Button .

    我写了以下子类:

    public class FocusedButton extends javafx.scene.control.Button {
    
        public FocusedButton ( ) {
            super ( );
            bindFocusToDefault ( );
        }
    
        public FocusedButton ( String text ) {
            super ( text );
            bindFocusToDefault ( );
        }
    
        public FocusedButton ( String text, Node graphic ) {
            super ( text, graphic );
            bindFocusToDefault ( );
        }
    
        private void bindFocusToDefault ( ) {
            defaultButtonProperty().bind(focusedProperty());
        }
    
    }
    

    要使用此代码,您需要在fxml-File中包含自定义类:

    <?import your-package.*?>
    

    如果你想使用Scene Builder,事情会变得更加困难:你需要在jar文件中导出自定义Button并将其添加到Scene Builder中,如here所述

  • 9

    为什么我总是回答三年的问题......?! ;-)无论如何,有人可能会发现它很有用(包括我自己) .

    要覆盖Enter键按下行为,我使用下面的函数在场景的按键事件过滤器中调用它:

    public static void overrideEnterKeyPressEvent(KeyEvent evt) {
        EventTarget eventTarget = evt.getTarget();
    
        if ((eventTarget instanceof TextArea) || (eventTarget instanceof TableView)) {
            return;
        }
    
        if (eventTarget instanceof Button) {
            Platform.runLater(() -> {
                KeyEvent newEventPressed = new KeyEvent(KeyEvent.KEY_PRESSED, " ", " ", KeyCode.SPACE, false, false, false, false);
                Event.fireEvent(eventTarget, newEventPressed);
                KeyEvent newEventReleased = new KeyEvent(KeyEvent.KEY_RELEASED, " ", " ", KeyCode.SPACE, false, false, false, false);
                Event.fireEvent(eventTarget, newEventReleased);
            });
            evt.consume();
            return;
        }
    
        Platform.runLater(() -> {
            KeyEvent tabEvent = new KeyEvent(KeyEvent.KEY_PRESSED, "", "\t", KeyCode.TAB, evt.isShiftDown(), false, false, false);
            Event.fireEvent(eventTarget, tabEvent);
        });
        evt.consume();
    }
    

    根据事件的目标,该功能的工作原理如下 . 对于TextArea或TableView,它是NoOp . 对于按钮,它会消耗Enter按事件并触发Space键按下和释放事件 . 对于所有其他控件,它还会消耗Enter press事件并触发Tab事件,因此按Enter键将焦点移动到下一个控件,就像Tab一样 .

    然后你只需为整个场景注册一个事件过滤器:

    scene.addEventFilter(KeyEvent.KEY_PRESSED, this::onSceneKeyPressedFilter);
    

    事件过滤器看起来像:

    private void onSceneKeyPressedFilter(KeyEvent evt) {
        switch (evt.getCode()) {
            case ENTER:
                if (evt.isControlDown() && FxTools.isAncestorNodeTargeted(evt.getTarget(), fxHBoxInputAp)) {
                    return; //let the events for the fxHBoxInputAp pane pass through
                }
                overrideEnterKeyPressEvent(evt);
                break;
            ...
            default:
                break;
        }
    }
    

相关问题