/* * Copyright 2014 Imagine Communications Corp. */ package acceleratorissue; import javafx.application.Application; import javafx.beans.binding.Bindings; import javafx.beans.property.SimpleIntegerProperty; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.control.Menu; import javafx.scene.control.MenuBar; import javafx.scene.control.MenuItem; import javafx.scene.input.KeyCharacterCombination; import javafx.scene.input.KeyCode; import javafx.scene.input.KeyCodeCombination; import javafx.scene.input.KeyCombination; import javafx.scene.layout.VBox; import javafx.stage.Stage; /** * * @author scott.palmer */ public class AcceleratorIssue extends Application { private SimpleIntegerProperty minusHits = new SimpleIntegerProperty(0); private SimpleIntegerProperty plusHits = new SimpleIntegerProperty(0); private Label hitMinusLabel = new Label(); private Label hitPlusLabel = new Label(); @Override public void start(Stage primaryStage) { // Note when used as a Scene accelerator, only one of these will fire, // even when both are added to the accelerator map. // But if you remove one, the other will fire - activated by the exact // same keypess. // On a US keyboard BOTH are mapped to CTRL + // (normal press is "-" and shifted press is "_") KeyCombination cmdMinus = new KeyCodeCombination(KeyCode.MINUS, KeyCombination.CONTROL_DOWN); KeyCombination cmdSubtract = new KeyCodeCombination(KeyCode.SUBTRACT, KeyCombination.CONTROL_DOWN); // This one seems to map to KeyCode.MINUS, but if the Scene also // has an accelerator on MINUS, and it gets this one from a MenuItem, // then the accelerator fires for both and a single keypress results in // two actions. // Note that if the MenuItem uses a KeyCodeCombination directly, no // duplicate events will happen. // I'm guessing "equals()" is used and it says the KeyCodeCombination // is not equal to the KeyCharacterCombination. So both are allowed // as simultaneous accelerators. // It appears that SUBTRACT is used for the Numeric keypad '-'key. // It really seems that this particlar KeyCombination should trigger for // either the main keyboard '-' key or the numeric keypad '-' key as // they both are used to type the same character and this is a Character // key binding. KeyCombination cmdMinusFromCharacter = new KeyCharacterCombination("-", KeyCombination.CONTROL_DOWN); // It appears that SUBTRACT is used for the Numeric keypad '-'key. // It appears that one must be careful to add only SUBTRACT to the // Scene accelerators when using // the numeric keypad '-'or the main keypad '-' and also have a menu // item show the same accelerator KeyCombination cmdPlus = new KeyCodeCombination(KeyCode.PLUS, KeyCombination.CONTROL_DOWN); KeyCombination cmdAdd = new KeyCodeCombination(KeyCode.ADD, KeyCombination.CONTROL_DOWN); KeyCombination cmdPlusAsShiftEquals = new KeyCodeCombination(KeyCode.EQUALS, KeyCombination.CONTROL_DOWN, KeyCodeCombination.SHIFT_DOWN); KeyCombination cmdPlusFromCharacter = new KeyCharacterCombination("+", KeyCombination.CONTROL_DOWN); hitMinusLabel.textProperty().bind(Bindings.format("\"-\" action happened %d times.", minusHits)); hitPlusLabel.textProperty().bind(Bindings.format("\"+\" action happened %d times.", plusHits)); MenuItem minusMenuItem = new MenuItem("Do Minus"); minusMenuItem.setAccelerator(cmdMinus); minusMenuItem.setOnAction(minusAction); MenuItem plusMenuItem = new MenuItem("Do Plus"); plusMenuItem.setAccelerator(cmdPlus); plusMenuItem.setOnAction(plusAction); Menu testMenu = new Menu("Test"); testMenu.getItems().add(minusMenuItem); MenuBar menus = new MenuBar(); menus.getMenus().add(testMenu); VBox root = new VBox(); VBox vbox = new VBox(8); vbox.setPadding(new Insets(16)); vbox.getChildren().addAll(new Label("Use CTRL+ \"-\" or CTRL + \"+\" to fire\n the action."), hitMinusLabel, hitPlusLabel); root.getChildren().addAll(menus,vbox); Scene scene = new Scene(root, 300, 250); scene.getAccelerators().put(cmdMinus, minusRunnable); scene.getAccelerators().put(cmdSubtract, minusRunnable); scene.getAccelerators().put(cmdMinusFromCharacter, minusRunnable); scene.getAccelerators().put(cmdPlus, plusRunnable); scene.getAccelerators().put(cmdAdd, plusRunnable); scene.getAccelerators().put(cmdPlusAsShiftEquals, plusRunnable); scene.getAccelerators().put(cmdPlusFromCharacter, plusRunnable); primaryStage.setScene(scene); primaryStage.setTitle("Accelerator Test"); primaryStage.show(); } /** * @param args the command line arguments */ public static void main(String[] args) { launch(args); } private EventHandler minusAction = new EventHandler() { @Override public void handle(ActionEvent event) { System.out.println("Using EventHandler"); doMinus(); event.consume(); } }; private EventHandler plusAction = new EventHandler() { @Override public void handle(ActionEvent event) { System.out.println("Using EventHandler"); doPlus(); event.consume(); } }; private Runnable minusRunnable = new Runnable() { @Override public void run() { System.out.println("Using Scene Accelerator"); doMinus(); } }; private Runnable plusRunnable = new Runnable() { @Override public void run() { System.out.println("Using Scene Accelerator"); doPlus(); } }; private void doMinus() { minusHits.set(minusHits.get() + 1); System.out.println(""+System.getProperty("javafx.runtime.version")); System.out.println("minus action"); } private void doPlus() { plusHits.set(plusHits.get() + 1); System.out.println("plus action"); } }