Search code examples
javauser-interfaceeventsjavafxtogglebutton

JavaFX - How do I turn off a ToggleButton's automatic setSelected(bool) feature?


When you add a basic ToggleButton it automatically has the ability to be selected or not via spacebar (if traversable, I turned that off though) or mouse click without having to write any code yourself. Is there an easy way to turn this off?

My current workaround which works is I create a method for the event on that ToggleButton called .setOnMouseClicked(this::handleMouseClick), and within that handler I call setSelected(false)... however I want to call a different method within that which has setSelected(false) instead, but it doesn't work and the ToggleButton gets selected still which I find odd.

I tried searching for someone with a similar problem, but the only thing I found maybe related was to create an EventFilter on a parent pane and capture the automatic events somehow to prevent them from firing? No idea how that works though. Any help is greatly appreciated.


Solution

  • There are multiple ways you can go about this:

    1. Use a filter
    2. Extend the ToggleButton class and override the fire method
    3. Add a listener to the selectedProperty that reverts the selected process, however without hacking a boolean into this it will result in you never being able to setSelected

    on 1.)

    This page explains everything there is to know about how events are handled and passed on. Using consume()within a handler will stop the event dispatch chain, but will not stop the event from being passed on to the handlers of that same node (in your example the ToggleButton). To do that you will need event filters:

        toggleButton.addEventFilter(MouseEvent.MOUSE_PRESSED, event -> {
            event.consume();
        });
        toggleButton.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
            if ( event.getCode() == KeyCode.SPACE ) {
                event.consume();
            }
        });
    

    on 2.)

    This is how the fire() method of the ToggleButton is implemented:

    @Override public void fire() {
        // TODO (aruiz): if (!isReadOnly(isSelected()) {
        if (!isDisabled()) {
            setSelected(!isSelected());
            fireEvent(new ActionEvent());
        }
    }
    

    As you can see it toggles the setSelected state, if the node (ToggleButton) is not disabled. You could extend the ToggleButton and override this fire method to stop this from happening. :)