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

时间:2014-09-10 06:34:17

标签: java events button javafx action

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

  

物业描述:

     

按钮的动作,无论何时调用   按钮被触发。这可能是由于用户点击了   按钮,鼠标,触摸事件,或按键,或者如果   开发人员以编程方式调用fire()方法。

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

P.S

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

3 个答案:

答案 0 :(得分:9)

您可以使用绑定

动态更改当前焦点按钮的默认按钮属性
btn.defaultButtonProperty().bind(btn.focusedProperty());

答案 1 :(得分:0)

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

我写了以下子类:

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并按照描述here将其添加到Scene Builder中

答案 2 :(得分:0)

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

要覆盖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按事件并触发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;
    }
}

-----编辑,因为我忘了包含isAncestorNodeTargeted()函数;感谢评论,罗伯特-----

public static boolean isDescendantOf(Node node, Node ancestor) {
    while ((node != null) && (node != ancestor)) {
        node = node.getParent();
    }
    return (node != null);
}


public static boolean isAncestorNodeTargeted(EventTarget target, Node ancestor) {
    return (target instanceof Node) ? isDescendantOf((Node) target, ancestor) : false;
}