![](/img/trans.png)
[英]JavaFX Button onAction property does not fire when Button pressed on touchscreen
[英]Fire Button's onAction with Enter in JavaFX
我是 JavaFx 的新手。 在我的 JavaFX 应用程序中,我设置了 onAction 属性,当我使用鼠标按下按钮时它工作正常。 即使用户按 Enter 按钮,我也想触发相同的操作。 我知道我可以使用偶数处理程序来做到这一点。 但是当我阅读 onAction JavaDoc 时,它说这个事件通过按键触发。
物业说明:
按钮的动作,只要按钮被触发就会调用。 这可能是由于用户使用鼠标单击按钮、触摸事件或按键,或者开发人员以编程方式调用了 fire() 方法。
但是当我按下 Enter 键时,什么也没有发生。 是文档错误吗? 有没有其他方法可以在不向按钮添加监听器的情况下实现这一目标?
聚苯乙烯
在评论之后我用空格键检查然后它被解雇了。 但我想将其设置为 Enter 键。 我有很多按钮。 我试过button.setDefaultButton(true);
但它不会被解雇。 我认为这是因为有不止一个按钮。 如果我仅将其设置为单个按钮,则它可以正常工作。 如何将其设置为多个按钮?
您可以使用绑定动态更改当前聚焦按钮的默认按钮属性
btn.defaultButtonProperty().bind(btn.focusedProperty());
如果您想将此应用于程序中的每个 Button,您可以将 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.*?>
如果你想使用场景生成器事情变得更加困难一点:你需要导出一个jar文件的自定义按钮,添加这场景Builder作为描述在这里
要覆盖 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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.