I'm a newbie to JavaFx. In my JavaFX application I have set onAction property and it works fine when I press the button using mouse. I want to fire the same even when user press Enter on button. I know I can use a even handler to do that.
But when I read the onAction JavaDoc it says that this event get fire by a key press.
Property description:
The button's action, which is invoked whenever
the button is fired. This may be due to the user clicking on the
button with the mouse, or by a touch event, or by a key press, or if
the developer programmatically invokes the fire() method.
But when I press Enter key nothing happens. Is it error in documentation? Are there any other way to achieve that without adding alistener to the button?
P.S
After the comments I checked with space key then it get fired. But I want to set that to Enter key.
I have many buttons. I tried button.setDefaultButton(true);
but it is not get fired. I think that is becacuse there are more than one button. If I set it just to a single button it works fine. How to set that to multiple buttons?
You can dynamically change the default button property of the currently focused button by using binding
btn.defaultButtonProperty().bind(btn.focusedProperty());
If you want to apply this to every Button in your program you can subclass the JavaFX-Button and bind this in the constructor. In your fxml-File you'll need to include your custom Button.
I wrote the following subclass:
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());
}
}
To use this Code you will need to include your custom class in the fxml-File:
<?import your-package.*?>
If you want to use the Scene Builder things get a little bit more difficult: You'll need to export your custom Button in a jar-file and add this to Scene Builder as described here
Why do I always answer three years old questions...?! ;-) Anyway, someone might find it useful (including myself).
To override the Enter key press behavior I use the function below calling it in the scene's key press event filter:
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();
}
Based on the event's target the function works as follows. For a TextArea or TableView, it's a NoOp. For a button, it consumes the Enter press event and fires Space key press and release events. And for all the other controls, it also consumes the Enter press event and fires a Tab event so pressing Enter moves focus to the next control just like Tab.
Then you just register an event filter for the whole scene:
scene.addEventFilter(KeyEvent.KEY_PRESSED, this::onSceneKeyPressedFilter);
And the event filter looks like:
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;
}
}