Search code examples
javafxeventhandler

JavaFX removeEventHandler not working as expected


I'm trying to remove the event handler from a FontAwesomeIconView object but it's not working. The event handler keeps working and I don't know why.

EventHandler<MouseEvent> glowIcon = (e) -> {
        FontAwesomeIconView icon = (FontAwesomeIconView) e.getSource();

        icon.setFill(Color.web("#ffb521"));
        scene.setCursor(Cursor.HAND);
    };

    EventHandler<MouseEvent> unglowIcon = (e) -> {
        FontAwesomeIconView icon = (FontAwesomeIconView) e.getSource();

        icon.setFill(Color.web("#000000"));
        scene.setCursor(Cursor.DEFAULT);
    };

    if (Session.getSession().isProjectCreator()) {
        newIcon.setFill(Color.web("#000000"));
        newIcon.addEventHandler(MouseEvent.MOUSE_ENTERED, glowIcon);
        newIcon.addEventHandler(MouseEvent.MOUSE_EXITED, unglowIcon);
    }else {

        newIcon.setFill(Color.web("#e8e8e8")); //It's changed to this color
        newIcon.removeEventHandler(MouseEvent.MOUSE_ENTERED, glowIcon);
        newIcon.removeEventHandler(MouseEvent.MOUSE_EXITED, unglowIcon);
    }

In the beginning the event handlers are ADDED, but when I remove them they keep working, when they shouldn't.


Solution

  • Without seeing a minimal reproducible example it is hard to tell. The most likely scenario from the code that you have posted is that glowIcon/unglowIncon are pointing at different lambdas when you add the handler vs remove it.

    Every time this code runs it will assign a different lambda reference to those variables, even if everything is exactly the same.

    EventHandler<MouseEvent> glowIcon = (e) -> {
        FontAwesomeIconView icon = (FontAwesomeIconView) e.getSource();
    
        icon.setFill(Color.web("#ffb521"));
        scene.setCursor(Cursor.HAND);
    };
    

    The solution is to make sure they are only called once and the reference to them is kept in your controller for as long as they are needed. Using final is a good defensive technique to make sure you don't accidentally reassign it somewhere and lose the reference you need to remove the handler.

    Something like:

    public class GlowController {
        private final EventHandler<MouseEvent> glowIcon = (e) -> {
            FontAwesomeIconView icon = (FontAwesomeIconView) e.getSource();
    
            icon.setFill(Color.web("#ffb521"));
            scene.setCursor(Cursor.HAND);
        };
    
        private final EventHandler<MouseEvent> unglowIcon = (e) -> {
            FontAwesomeIconView icon = (FontAwesomeIconView) e.getSource();
    
            icon.setFill(Color.web("#000000"));
            scene.setCursor(Cursor.DEFAULT);
        };
    
        public void doSomething() {
            if (Session.getSession().isProjectCreator()) {
                newIcon.setFill(Color.web("#000000"));
                newIcon.addEventHandler(MouseEvent.MOUSE_ENTERED, glowIcon);
                newIcon.addEventHandler(MouseEvent.MOUSE_EXITED, unglowIcon);
            }else {
    
                newIcon.setFill(Color.web("#e8e8e8")); //It's changed to this color
                newIcon.removeEventHandler(MouseEvent.MOUSE_ENTERED, glowIcon);
                newIcon.removeEventHandler(MouseEvent.MOUSE_EXITED, unglowIcon);
            }
        }
    }