F1 Key Binding Presented as Standard Accelerator |
Keyboard shortcuts in JavaFX are implemented using a KeyCombination. For example, pressing the Control key and the W key at the same time can execute a close command. In Scene Builder, you can configure this type of shortcut using an accelerator. The accelerator is one or more modifiers (Control, Shift, Alt, Command) plus another key of your choosing, say "W", "S", or "N".
Shortcut Accelerators
This screenshot of a PC app shows a set of accelerators applied to using the SHORTCUT modifier which bridges the difference between different platforms. Note that the New, Save and Close commands are bound to the Control-N, Control-S, and Control-W KeyCombinations.
PC Version of the App's Shortcuts |
Mac Using Command Shortcuts |
Scene Builder Defining an Accelerator |
Although there is a "No" option in Scene Builder 2.0's ChoiceBox, I haven't been able to get a direct key binding working. That is, I want to press the F1 key without a modifier to execute a showHelp() function. I also want the F1 key to display a visual cue in the MenuItem itself as is done with the other accelerators. In Scene Builder, my selection of No/F1 doesn't seem to be saved. So, I define this in code.
First, I give my MenuItem an fx:id and add it as an @FXML member in the controller class.
@FXML MenuItem miHelp;
Next, I add this KeyCombination to the @FXML initialize() method of the JavaFX controller.
miHelp.setAccelerator( KeyCombination.keyCombination("F1") );
Finally, I place an EventFilter on each and every Scene in the app. In this particular app, I'm using a common view base class so I'm in a leveraged position that allows me to add this in a single location. My help isn't context-sensitive, so executing the same help command for all areas is fine.
stage.getScene().addEventFilter(KeyEvent.KEY_PRESSED, (evt) -> { if( evt.getCode() == KeyCode.F1 ) { helpDelegate.showHelp(); } });
helpDelegate() is a Guice-injected object that executes the help function. This help function is also called from a standard MenuItem action handler for when the Help > Help item is selected.
Just adding the EventFilter to the Scene gives you a Scene-wide ability to call a global command like help. Needing the define the modifier-less KeyCombination outside of Scene Builder is unfortunate, but important so that the UI is consistent and the users can learn about the shortcuts by using the app itself.
No need to write code for that.
ReplyDeleteJust define the accelerator in SceneBuilder with a modifier, e.g. 'shortcut_down'.
Then open the fxml file in an editor, search for the accelerator and set "DOWN" to "UP", as in:
KeyCodeCombination code="F1" alt="UP" control="UP" meta="UP" shift="UP" shortcut="UP"
Save, re-open the scene in SceneBuilder, and it will display the shortcut correctly as "F1".
Good tip, although I'm still looking for Scene Builder to do this so that I don't have to hand-edit the FXML (or write extra code).
Delete