Using JavaFX 2.2 Mnemonics (and Accelerators)

I am trying to make JavaFX Mnemonic work. I have a button on the stage and I want this event to press Ctrl + S. Here is the sceleton code:

@FXML public Button btnFirst; btnFirst.getScene().addMnemonic(new Mnemonic(btnFirst, new KeyCodeCombination(KeyCode.S, KeyCombination.CONTROL_DOWN))); 

The mnemonicParsing button is false. (Well, trying to make this work, I tried to set it to true, but there was no result). The JavaFX documentation says that when Mnemonic is registered on the Scene and the KeyCombination reaches the scene not loaded, the target Node will be sent an ActionEvent. But that doesn't work, maybe I'm wrong ...

I can use standard button mnemonics (by setting mnemonicParsing to true and prefixing the letter "F" with an underscore). But in this way, the user must use the Alt key, which causes some strange actions in browsers using the menu bar (if the application is embedded in a web page than the browser menu activated after the activation button event by pressing Alt + S). In addition, the standard way makes it impossible to create shortcuts such as Ctrl + Shift + F3, etc.

So, if there is a way to do this?

+8
button javafx javafx-2 shortcut
source share
1 answer

For your use case, I think you really want to use the accelerator, not the mnemonics.

 button.getScene().getAccelerators().put( new KeyCodeCombination(KeyCode.S, KeyCombination.SHORTCUT_DOWN), new Runnable() { @Override public void run() { button.fire(); } } ); 

In most cases, it is recommended to use KeyCombination.SHORTCUT_DOWN as a modifier specifier, as in the code above. A good explanation of this in the KeyCombination documentation:

The shortcut modifier is used to represent the modifier key, which is commonly used in keyboard shortcuts on the host platform. This is for example management on Windows and meta (command key) on Mac. Using developers, shortcut keys can create platform-independent shortcuts. Thus, the keyboard shortcut β€œShortcut + C” is processed internally as β€œCtrl + C” on Windows and β€œMeta + C” on Mac.

If you want to specifically encode only the keyboard shortcut Ctrl + S, you can use:

 new KeyCodeCombination(KeyCode.S, KeyCombination.CONTROL_DOWN) 

Here is an example:

 import javafx.animation.*; import javafx.application.Application; import javafx.event.*; import javafx.geometry.Pos; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.image.*; import javafx.scene.input.*; import javafx.scene.layout.VBox; import javafx.stage.Stage; import javafx.util.Duration; public class SaveMe extends Application { @Override public void start(final Stage stage) throws Exception { final Label response = new Label(); final ImageView imageView = new ImageView( new Image("http://icons.iconarchive.com/icons/gianni-polito/colobrush/128/software-emule-icon.png") ); final Button button = new Button("Save Me", imageView); button.setStyle("-fx-base: burlywood;"); button.setContentDisplay(ContentDisplay.TOP); displayFlashMessageOnAction(button, response, "You have been saved!"); layoutScene(button, response, stage); stage.show(); setSaveAccelerator(button); } // sets the save accelerator for a button to the Ctrl+S key combination. private void setSaveAccelerator(final Button button) { Scene scene = button.getScene(); if (scene == null) { throw new IllegalArgumentException("setSaveAccelerator must be called when a button is attached to a scene"); } scene.getAccelerators().put( new KeyCodeCombination(KeyCode.S, KeyCombination.SHORTCUT_DOWN), new Runnable() { @Override public void run() { fireButton(button); } } ); } // fires a button from code, providing visual feedback that the button is firing. private void fireButton(final Button button) { button.arm(); PauseTransition pt = new PauseTransition(Duration.millis(300)); pt.setOnFinished(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { button.fire(); button.disarm(); } }); pt.play(); } // displays a temporary message in a label when a button is pressed, // and gradually fades the label away after the message has been displayed. private void displayFlashMessageOnAction(final Button button, final Label label, final String message) { final FadeTransition ft = new FadeTransition(Duration.seconds(3), label); ft.setInterpolator(Interpolator.EASE_BOTH); ft.setFromValue(1); ft.setToValue(0); button.setOnAction(new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent event) { label.setText(message); label.setStyle("-fx-text-fill: forestgreen;"); ft.playFromStart(); } }); } private void layoutScene(final Button button, final Label response, final Stage stage) { final VBox layout = new VBox(10); layout.setPrefWidth(300); layout.setAlignment(Pos.CENTER); layout.getChildren().addAll(button, response); layout.setStyle("-fx-background-color: cornsilk; -fx-padding: 20; -fx-font-size: 20;"); stage.setScene(new Scene(layout)); } public static void main(String[] args) { launch(args); } } // icon license: (creative commons with attribution) http://creativecommons.org/licenses/by-nc-nd/3.0/ // icon artist attribution page: (eponas-deeway) http://eponas-deeway.deviantart.com/gallery/#/d1s7uih 

Output Example:

Sample program output

+20
source share

All Articles