Java FX - 事件处理的不同方面

Java FX - different aspects of event handling

我正在努力了解 Java FX 中事件处理的不同方面。我已经通读了 Oracle material 但我仍然有点困惑,想知道是否有人可以以简洁的方式解释一些不同选项的差异和关键用途。

首先,据我所知,有事件处理程序和事件过滤器,然后是方便的方法。那么 Handlers 和 Filters 之间的主要区别是什么以及为什么我会使用一个而不是另一个。此外,使用 addEventHandler(...) 添加事件处理程序而不是使用便捷方法有什么好处?根据我自己的测试,我相信使用 addEventHandler(...) 可以将多个事件处理程序附加到给定控件,而使用 setOnEvent-type(...) 只允许附加一个事件处理程序,因为它会覆盖 属性 每次设置。还有其他区别吗?

然后是 ChangeListener 和 InvalidationListener 的主题 - 我认为 ChangeListener 是一种事件处理程序,专门用于侦听(属性的)更改事件,我的想法是否正确?除了 JavaFX 属性和绑定上的 Oracle 页面之外,我似乎找不到许多使用 ChangeListener 的示例 - 有人知道好的指南吗?此外,简单来说,我什么时候会在 ChangeListener 和 InvalidationListener 之间进行选择?

最后,有时是否可以通过传统的 EventHandler 或 ChangeListener 模拟相同的事件处理过程 - 例如可以使用 ActionEvent 处理按钮单击 - 有没有办法通过 ChangeListener 来完成?我可以看到理论上您可以向 onActionProperty 添加一个更改侦听器,但我认为单击按钮时不会调用它,而是如果 setOnAction 实际上更改了附加的事件处理程序?

So what's the key difference between Handlers and Filters and why I would use one over another.

关键区别在于每一个发生的时间。事件过滤器在事件捕获阶段调用,该阶段发生在事件冒泡阶段(调用事件处理程序)之前。因此,您可以在通知处理程序之前过滤(使用)您不想处理的事件。大多数时候你只想使用一个处理程序而不用担心过滤器。但是,在某些情况下您需要过滤事件。例如,假设一个游戏中鼠标操作者移动游戏角色。如果用户打开游戏内菜单,您不希望他能够单击 "through" 菜单进入游戏并在菜单打开时移动角色。一种可能的方法是过滤这些鼠标事件并在它们到达注册处理程序的节点之前使用它们。您当然可以将鼠标处理程序附加到不同的东西而不是整个场景,但这超出了示例中强调的重点。

顾名思义,便利处理程序是为了方便而存在的。它减少了样板代码并允许简单 API。根据 JavaFX 文档,它们在事件链中最后被调用。所以如果你只对一种事件类型感兴趣,那么这些方法应该是首选。

总而言之,按此顺序使用便利和事件处理程序,如果需要对事件调度进行更多控制,您还可以添加过滤器。

Furthermore, in simple terms, when would I choose between a ChangeListener and InvalidationListener?

更改侦听器会在值实际更改时收到通知。为了识别变化,必须重新计算该值。所以当你将这样一个监听器添加到一个可观察值时,它不再是惰性评估而是热切评估。

当某个值不再有效时,将通知失效侦听器。然而,这并不意味着价值已经改变。这允许我们在实际不知道值的情况下触发失效事件。该值将在访问之前进行评估。

因此,简单来说,如果您需要知道可观察对象的新值,请使用 ChangeListener,否则使用 InvalidationListener。

I can see that you could theoretically add a change listener to the onActionProperty, but I think this would not be invoked when the button is clicked, but instead if setOnAction actually changed the event handler that was attached?

是的,你是对的。要处理按钮点击,您需要使用 setOnAction()ChangeListener 与事件处理无关。