3

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!

Till F.
  • 189
  • 1
  • 9

1 Answers1

2

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
Matt
  • 3,052
  • 1
  • 17
  • 30
  • Ok, thanks. That's the solution I was thinking of myself. This means that we re-implement the click-behavior of the checkbox. Maybe you have some clever idea how we can re-use the default handler? Otherwise we will have to consider the `indeterminate` state as well, i.e. if `allowIndeterminate` is true. – Till F. Jan 14 '19 at 17:10