Search code examples
javafxmouseeventmodifier-key

JavaFX Events for Mouse Interactions are not triggered if Key is pressed


JavaFX does not execute events like the ActionEvent for Button or CheckBox, if a modifier key like CTRL or SHIFT is pressed. As far as I understand this behavior is implemented in ButtonBehavior (e.g. note the expression ! keyDown in the following method from that class):

@Override public void mouseReleased(MouseEvent e) {
    // if armed by a mouse press instead of key press, then fire!
    final ButtonBase button = getControl();
    if (! keyDown && button.isArmed()) {
        button.fire();
        button.disarm();
    }
}

First of all, I do not really understand the reason for this. What is the purpose of not firing a button if a key is pressed?

This is my use-case: I want to implement a checkbox that can be checked/unchecked as normal. It will toggle some state in a model. But it should have an additional feature: if the user presses some key like CTRL while checking/unchecking with the mouse, an additional flag called "locked" or "protected" should be set in the model, which will prevent that the state can be overwritten by some other logic of the application.

This should give an idea about the use-case, but if not it doesn't really matter for my actual question: How can I make it possible that a CheckBox can still be toggled (or a Button be pressed) even though the user presses a modifier key?

Thanks for your help!


Solution

  • That is odd you can implement it yourself like so

    public class Main extends Application {
    
        @Override
        public void start(Stage primaryStage) throws Exception{
            VBox vBox = new VBox();
            vBox.setAlignment(Pos.CENTER);
    
            CheckBox checkBox = new CheckBox();
            checkBox.setOnMouseClicked(event -> {
                if(event.isControlDown()) {
                    System.out.print("Control down click ");
                    checkBox.setSelected(!checkBox.isSelected());
                }
                else
                    System.out.print("Normal click ");
    
                System.out.println("Checked Status:"+checkBox.isSelected());
            });
    
            Button button = new Button("Button");
            button.setOnMouseClicked(event -> {
                if(event.isControlDown())
                    System.out.println("Control down click");
                else
                    System.out.println("Normal click");
            });
    
            vBox.getChildren().addAll(new Label("Click the box"),checkBox,button);
    
    
            primaryStage.setScene(new Scene(vBox));
            primaryStage.show();
        }
    
        public static void main(String[] args) { launch(args); }
    
    }
    

    The output for CheckBox:

    Normal click Checked Status:true
    Normal click Checked Status:false
    Control down click Checked Status:true
    Control down click Checked Status:false
    

    The output for Button:

    Normal click
    Control down click