JavaFX removeEventHandler 没有按预期工作

JavaFX removeEventHandler not working as expected

我正在尝试从 FontAwesomeIconView 对象中删除事件处理程序,但它不起作用。事件处理程序一直在工作,我不知道为什么。

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);
    }

一开始添加了事件处理程序,但是当我删除它们时它们会继续工作,而实际上它们不应该。

如果没有看到最小的可重现示例,则很难判断。您发布的代码中最可能的情况是 glowIcon/unglowIncon 在您添加处理程序与删除处理程序时指向不同的 lambda。

每次运行此代码时,它都会为这些变量分配一个不同的 lambda 引用,即使一切都完全相同。

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

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

解决方案是确保它们只被调用一次,并且只要需要它们,对它们的引用就会保留在您的控制器中。使用 final 是一种很好的防御技术,可确保您不会不小心将其重新分配到某处并丢失删除处理程序所需的引用。

类似于:

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);
        }
    }
}

万一有人在试图弄清楚为什么删除事件侦听器时偶然发现了这个问题,请添加:

vbox.setOnMouseClicked(eventHandler);

不会因 removeEventHandler 而被删除。事实证明,您需要使用以下方式添加事件处理程序:

vbox.addEventHandler(MouseEvent.MOUSE_CLICKED, eventHandler);

删除调用工作。

我原以为无论您以何种方式添加处理程序,它都能正常工作,但事实并非如此:|