简体   繁体   中英

JavaFX: handle key combination and mouse event simultaneously

I need to react on a key + mouse event combination like:

Ctrl + Shift + R + left_mousebutton_clicked

But I can't figure out, how to handle the "left_mousebutton_clicked" only if the key combination of Ctrl + Shift + R occurs.

A solution like

if(MouseEvent.isControlDown())

will not work cause there may be different key combinations with any kind of the letters.

Any ideas?

You can use a container to store the currently pressed keys:

private final Set<KeyCode> pressedKeys = new HashSet<>();

You can attach listeners to the Scene of the control the you want to target with the mouse-click:

scene.setOnKeyPressed(e -> pressedKeys.add(e.getCode()));
scene.setOnKeyReleased(e -> pressedKeys.remove(e.getCode()));

While these listeners maintain the set, you can simply attach a listener on the target Node :

Label targetLabel = new Label("Target Label");
targetLabel.setOnMouseClicked(e -> {
    if (e.getButton() == MouseButton.PRIMARY &&
        pressedKeys.contains(KeyCode.R) && 
        e.isShortcutDown() &&
        e.isShiftDown()) 

        System.out.println("handled!");
});

Example Application :

public class MouseClickExample extends Application {

    private final Set<KeyCode> pressedKeys = new HashSet<>();

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

    @Override public void start(Stage stage) {
        VBox root = new VBox();
        Scene scene = new Scene(root, 450, 250);

        scene.setOnKeyPressed(e -> pressedKeys.add(e.getCode()));
        scene.setOnKeyReleased(e -> pressedKeys.remove(e.getCode()));

        Label targetLabel = new Label("Target Label");
        targetLabel.setOnMouseClicked(e -> {
            if (e.getButton() == MouseButton.PRIMARY && pressedKeys.contains(KeyCode.R) && e.isShortcutDown() && e.isShiftDown())
                System.out.println("handled!");
        });

        root.getChildren().add(targetLabel);
        stage.setScene(scene);
        stage.show();
    }
}

Note: The meta keys are also stored in the Set but they are not used by this example. The meta keys could be also checked in the set rather than using methods on the mouse-event.

Both ctrl and shift can be done the way you aproached it there. The left mouse key is the PrimaryButton

if(mouseEvent.isControlDown() && mouseEvent.isShiftDown && mouseEvent.isPrimaryKeyDown){
    // Do your stuff here
}

And for the "non special" key (like r) I thnk you need to make a global boolean - and a seperate keyevent listener for it. So:

boolean rIsDown = false;

scene.setOnKeyPressed(e -> {
if(e.getCode() == KeyCode.R){
    System.out.println("r was pressed");
    //set your global boolean "rIsDown" to true
}
});

scene.setOnKeyReleased(e -> {
if(e.getCode() == KeyCode.R){
    System.out.println("r was released");
    //set it rIsDown back to false
}
});

Then use your it together with the other conditions...

    if(mouseEvent.isControlDown() && mouseEvent.isShiftDown && rIsDown &&  mouseEvent.isPrimaryKeyDown){
    // Do your stuff here
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM