JavaFX strange menu accelerator behaviour

2019-04-14 10:54发布

问题:

I noticed a really strange behaviour with menu accelerators on the JavaFX (system) menu. Some key combinations don't work at all and others are interpreted as the wrong key.

For instance, when you use the CMD+CLEAR key as accelerator, it gets changed as the CMD+Page Down down key (both in the menu text and in the actual response to a keyboard event). The '-' (MINUS) key doesn't work well at all and while, CMD + - shows up well in the menu, it never gets triggered when you press the keys. When on the other hand you add the ALT key (i.e., you press CMD+ALT+-), the CMD- events does get triggered (but not the CMD+ALT+- one).

Any idea what's going on, or is this a (know) bug?

I have created below sample program to illustrate this. Note: I'm on a Mac.

package menuaccelerator;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import javafx.scene.control.TextArea;
import javafx.scene.input.KeyCombination;
import javafx.scene.layout.StackPane;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class MenuAccelerator extends Application {

    // Counter for the event number
    int eventNr = 0;

    @Override
    public void start(Stage primaryStage) {
        // Text Area for displaying the events
        TextArea events = new TextArea();
        events.setEditable(false);
        events.setOnKeyPressed((e) -> {
            System.out.println("Key Event(" + ++eventNr + "): " + e);
            events.appendText((eventNr == 1 ? "" : "\n") + "KeyCode(" + eventNr + "): " + e.getCode());
            e.consume();
        });

        // Menu Bar & Menu
        MenuBar menuBar = new MenuBar();
        menuBar.setUseSystemMenuBar(true);
        Menu menu = new Menu("Accelerator Test");
        menuBar.getMenus().add(menu);

        // Build menu
        for (String item : new String[]{"Shortcut+PLUS", "Shortcut+Alt+PLUS",
                                        "Shortcut+MINUS", "Shortcut+Alt+MINUS",
                                        "Shortcut+PAGE__UP", "Shortcut+Alt+PAGE__UP",
                                        "Shortcut+PAGE__DOWN", "Shortcut+Alt+PAGE__DOWN",
                                        "Shortcut+CLEAR"}) {
            MenuItem menuItem = new MenuItem(item);
            menuItem.setAccelerator(KeyCombination.keyCombination(item));
            menuItem.setOnAction((ActionEvent e) -> {
                System.out.println("Menu Event(" + ++eventNr + "): " + e);
                events.appendText((eventNr == 1 ? "" : "\n") + "Menu Event(" + eventNr + "): " + ((MenuItem) e.getSource()).getText());
                e.consume();
            });
            menu.getItems().add(menuItem);
        }

        // Create scene
        StackPane root = new StackPane();
        VBox vbox = new VBox(10);
        vbox.setAlignment(Pos.CENTER);
        vbox.getChildren().add(events);
        root.getChildren().add(vbox);
        root.getChildren().add(menuBar);
        Scene scene = new Scene(root, 300, 200);

        // Display scene
        primaryStage.setTitle("Accelerator Test");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }

}