setOnXXX()方法和addEventHandler()JavaFx之间的差异

setOnXXX()方法和addEventHandler()JavaFx之间的差异,java,javafx,Java,Javafx,我正在尝试学习JavaFX事件处理。我发现我们可以通过两种方式注册事件 一种是方便的方法,如setOnAction(EventHandler),setOnMouseClicked(EventHandler) 第二种方法是使用addEventHandler(MouseEvent.MOUSE\u CLICKED,EventHandler) 但是我很困惑他们之间有什么区别?如何决定哪一个合适 我已经使用这两种方法测试并注册了两个事件处理程序,它们都运行良好 Button btn = new Butto

我正在尝试学习JavaFX事件处理。我发现我们可以通过两种方式注册事件

一种是方便的方法,如
setOnAction(EventHandler)
setOnMouseClicked(EventHandler)

第二种方法是使用
addEventHandler(MouseEvent.MOUSE\u CLICKED,EventHandler)

但是我很困惑他们之间有什么区别?如何决定哪一个合适

我已经使用这两种方法测试并注册了两个事件处理程序,它们都运行良好

Button btn = new Button("Click Me One!");
    btn.setOnMouseEntered(new EventHandler<MouseEvent>(){
        @Override
        public void handle(MouseEvent e){
            System.out.println("Mouse Entered on Click Me One");
        }
    });

    btn.setOnMouseExited(new EventHandler<MouseEvent>(){
        @Override
        public void handle(MouseEvent e){
            System.out.println("Mouse Exited from Click Me One");
        }
    });


    Button btn2 = new Button("Click Me Two!");
    btn2.addEventHandler(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>(){
        @Override
        public void handle(MouseEvent e){
            System.out.println("Mouse Entered on Click Me Two");
        }
    });
    btn2.addEventHandler(MouseEvent.MOUSE_EXITED, new EventHandler<MouseEvent>(){
        @Override
        public void handle(MouseEvent e){
            System.out.println("Mouse Exited from Click Me Two");
        }
    });
我还通过定义事件处理程序进行了检查

Button btn2 = new Button("Click Me Two!");
        // Define an event handler
        EventHandler<InputEvent> handler = new EventHandler<InputEvent>() {
            public void handle(InputEvent event) {
                System.out.println("Handling event " + event.getEventType()); 

            }
        };
        btn2.addEventHandler(MouseEvent.MOUSE_ENTERED, handler);
        btn2.addEventHandler(MouseEvent.MOUSE_EXITED, handler);

        btn2.setOnMouseEntered(handler);
        btn2.setOnMouseExited(handler);

查看
节点的javadoc(从
setOnXXX
调用):

设置用于此事件类型的处理程序一次只能指定一个这样的处理程序。此处理程序保证 在使用添加处理程序后,作为最后一个调用 addEventHandler(javafx.event.EventType,javafx.event.EventHandler)}


因此,如果您只需要一个
EventHandler
,那么使用哪种方法没有什么区别。但是,如果您需要为同一
事件类型应用多个
事件处理程序
,则必须使用
addEventhandler

添加它们。在对自己进行测试后,我得到了的确切含义,使用方便的方法只能有一个相同类型的处理程序。所以我要回答我自己的问题

我发现
setOnXXX()
方法和
addEventHandler

1:首先执行向
addEventHandler()注册的事件。以下是示例。

Button btn = new Button("Hover Me!");

btn.setOnMouseEntered(new EventHandler<MouseEvent>() {
    public void handle(MouseEvent event) {
        System.out.println("Handling event with Convience Method"); 
    }
});
btn.addEventHandler(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() {
    public void handle(MouseEvent event) {
        System.out.println("Handling event with addEventHandler"); 
    }
});
在阅读了James_D的评论后,我添加了第1个不同之处的段落

一个节点可以注册多个处理程序。每一个的顺序 根据事件类型的层次结构调用处理程序。处理者 对于特定的事件类型,在泛型的处理程序之前执行 事件类型。例如,KeyEvent.KEY_类型事件的处理程序 在InputEvent.ANY事件的处理程序之前调用。命令 其中未指定在同一级别执行两个处理程序, 但由 使用便利方法中描述的便利方法包括 最后执行

2:第二个区别是,您可以使用
addEventHandler()添加具有相同
EventType
(正如我使用鼠标输入的事件)的多个处理程序但在
setOnXXX()的情况下将执行上次注册的事件处理程序。这是一个例子

Button btn = new Button("Hover Me!");

btn.setOnMouseEntered(new EventHandler<MouseEvent>() {
    public void handle(MouseEvent event) {
        System.out.println("Handling event 1 with Convenience Method"); 
    }
});
btn.setOnMouseEntered(new EventHandler<MouseEvent>() {
    public void handle(MouseEvent event) {
        System.out.println("Handling event 2 with Convenience Method"); 
    }
});
btn.addEventHandler(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() {
    public void handle(MouseEvent event) {
        System.out.println("Handling event 1 with addEventHandler"); 
    }
});

btn.addEventHandler(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() {
    public void handle(MouseEvent event) {
        System.out.println("Handling event 2 with addEventHandler"); 
    }
});
如您所见,我使用两种方法注册了两个事件处理程序。但以便利方法的方式执行最后一个事件处理程序。为了完成答案,让我从jns的答案中复制一段

因此,如果您只需要一个
EventHandler
,那么哪一个没有区别 你使用的方法。但是,如果需要应用多个EventHandler 对于相同的
EventType
您必须使用
addEventhandler


你的代码与你的问题无关。您的代码中没有任何地方使用了
addEventHandler
。(为了记录,您应该始终对按钮使用setOnAction,而不是setOnMouseClicked。不是每个用户都使用鼠标激活按钮。)@VGR我已经更新了代码,请现在检查。如果没有其他内容,则显式事件属性用于准确枚举特定类的有效事件。@VGR您能解释更多吗?这些例子对我来说是额外的奖励。想象一下,根本就没有设置……方法。您如何知道某些类(如Button)支持
EventType
?每个节点子类都必须记录它所支持的其他事件类型……如果开发人员在使用它之前定期阅读一个类的文档以及它从中继承的所有类的文档,这将很好,但实际上他们很少这样做。javadoc link将很有帮助。你能给我这段文字的链接吗?我已经在上面解释过,我可以使用这两种技术添加多个事件处理程序?我很困惑,你能给我一些示例代码来描述它们之间的区别吗?并且
一次只能指定一个这样的处理程序
我已经用set方法添加了两个事件,那么它为什么工作?设置用于此事件类型的处理程序(例如MouseEvent.MOUSE_退出)。只能有一个这样的处理程序(对于此事件类型)。尝试为同一事件类型添加多个侦听器,例如使用
setonmouseexted
,您将看到只有最后添加的侦听器将被调用。两人都在执行
setonmouseintered
setonmouseexted
请阅读我的相关代码。您能用代码示例更新您的答案吗?它们的执行顺序是否实际记录在案(即,您能否依赖该功能),或者这正是您测试过的当前实现中发生的情况?在这里您可以发现
没有指定同一级别的两个处理程序的执行顺序,例外情况是,由“使用便利方法”中描述的便利方法注册的处理程序将在最后执行。
您应该将其添加到答案中以使其生效complete@James_D是的,我添加了。这是错误的-
但是在setOnXXX()的情况下;最后注册的事件处理程序将执行。
当您通过setOnXXX()设置处理程序时,此处理程序保存在ObjectProperty onXXX中。因此,一个属性只能有一个处理程序。这就是为什么当您第二次调用setOnXXX时,您只是用这个新的处理程序替换以前的处理程序。
Button btn = new Button("Hover Me!");

btn.setOnMouseEntered(new EventHandler<MouseEvent>() {
    public void handle(MouseEvent event) {
        System.out.println("Handling event with Convience Method"); 
    }
});
btn.addEventHandler(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() {
    public void handle(MouseEvent event) {
        System.out.println("Handling event with addEventHandler"); 
    }
});
Handling event with addEventHandler
Handling event with Convience Method
Button btn = new Button("Hover Me!");

btn.setOnMouseEntered(new EventHandler<MouseEvent>() {
    public void handle(MouseEvent event) {
        System.out.println("Handling event 1 with Convenience Method"); 
    }
});
btn.setOnMouseEntered(new EventHandler<MouseEvent>() {
    public void handle(MouseEvent event) {
        System.out.println("Handling event 2 with Convenience Method"); 
    }
});
btn.addEventHandler(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() {
    public void handle(MouseEvent event) {
        System.out.println("Handling event 1 with addEventHandler"); 
    }
});

btn.addEventHandler(MouseEvent.MOUSE_ENTERED, new EventHandler<MouseEvent>() {
    public void handle(MouseEvent event) {
        System.out.println("Handling event 2 with addEventHandler"); 
    }
});
Handling event 1 with addEventHandler
Handling event 2 with addEventHandler
Handling event 2 with Convenience Method