【问题标题】:Fire Button's onAction with Enter in JavaFX在 JavaFX 中使用 Enter 触发按钮的 onAction
【发布时间】:2014-11-03 17:03:16
【问题描述】:

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

属性描述:

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

但是当我按下 Enter 键时,什么也没有发生。是文档中的错误吗?有没有其他方法可以在不向按钮添加监听器的情况下实现这一点?

附言

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

【问题讨论】:

  • 按键时按钮是否有焦点?在 Windows 7 上,仅当我按下空格键时才会触发操作事件。
  • 是的。我在按键之前将焦点设置在按钮上
  • 当你按空格而不是回车时,处理程序是否被调用?
  • @ThusithaThilinaDayaratne,我有一个想法,您应该进行测试。 btn.defaultButtonProperty().bind(btn.focusedProperty())

标签: java events button javafx action


【解决方案1】:

要覆盖 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;
}

【讨论】:

  • FxTools.isAncestorNodeTargeted() 使用什么依赖项?
  • 对不起,我的错。这是一个我忘记包含的简单功能。使用较新的 JavaFx 版本可能有更好的方法,但我不知道。我编辑了答案。
【解决方案2】:

如果您想将此应用于程序中的每个按钮,您可以继承 JavaFX-Button 并将其绑定到构造函数中。在您的 fxml 文件中,您需要包含您的自定义按钮。

我写了以下子类:

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 文件中包含您的自定义类:

<?import your-package.*?>

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

【讨论】:

    【解决方案3】:

    你可以通过绑定来动态改变当前焦点按钮的默认按钮属性

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

    【讨论】:

      猜你喜欢
      • 2020-10-07
      • 1970-01-01
      • 2017-03-26
      • 2018-02-13
      • 2018-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多