我试图了解JavaFX中事件处理的不同方面。我已经阅读了甲骨文的材料,但我仍然有点困惑,想知道是否有人能以简洁的方式解释一些不同选项的差异和关键用途。
首先,从我所看到的有事件处理程序和事件过滤器,然后是方便方法。那么处理程序和过滤器之间的主要区别是什么,以及为什么我会使用一个而不是另一个。此外,使用addEventHandler(…)而不是使用方便方法添加事件处理程序有什么好处?从我自己的测试来看,我相信使用addEventHandler(…)您可以将多个事件处理程序附加到给定的控件,而使用setOnEvent-type(…)只允许附加一个事件处理程序,因为它每次设置时都会覆盖属性。还有其他区别吗?
然后是ChangeListener和InvalidationListener的主题——我认为ChangeListener是一种事件处理程序,专门用于侦听(属性的)更改事件,这是正确的吗?除了关于JavaFX属性和绑定的Oracle页面之外,我似乎找不到很多使用ChangeListener的例子——有人知道一个好的指南吗?此外,简单来说,我什么时候会在ChangeListener和InvalidationListener之间做出选择?
最后,是否有可能有时通过传统的EventHandler或ChangeListener来模拟相同的事件处理过程-例如,可以使用ActionEvent处理按钮单击-是否有办法通过ChangeListener来完成?我可以看到理论上您可以将更改侦听器添加到onActionProperty,但我认为单击按钮时不会调用它,而是如果setOnAction实际更改了附加的事件处理程序?
那么处理程序和过滤器之间的主要区别是什么,以及为什么我会使用一个而不是另一个。
关键区别在于每个事件发生的时间。事件过滤器在事件捕获阶段调用,该阶段发生在事件冒泡阶段(调用事件处理程序)之前。因此,您可以在通知处理程序之前过滤(消费)您不想处理的事件。大多数时候,您只想简单地使用处理程序而不必担心过滤器。然而,有些情况下您需要过滤事件。例如,想象一个游戏,鼠标处理程序移动游戏角色。如果用户打开游戏内菜单,您不希望他能够在菜单打开时单击“通过”菜单进入游戏并移动角色。一种可能的方法是过滤这些鼠标事件,并在它们到达处理程序注册的节点之前使用它们。您当然可以将鼠标处理程序附加到不同的东西而不是整个场景,但它超出了示例中强调的要点。
方便处理程序,顾名思义,是为了方便而存在的。它减少了样板代码并允许轻松的API。根据JavaFX文档,它们在事件链中被称为最后一个。因此,如果您只有一种感兴趣的事件类型,那么这些方法应该是首选。
综上所述,按此顺序使用便利性和事件处理程序,如果需要对事件调度进行更多控制,您还可以添加过滤器。
此外,简单来说,我什么时候会在ChangeListener和InvalidationListener之间进行选择?
更改侦听器在值实际上发生更改时收到通知。为了识别更改,必须重新计算该值。因此,当您将此类侦听器添加到可观察值时,它不再是懒惰地评估,而是急切地评估。
当值不再有效时,会通知无效侦听器。但是,这并不意味着该值已更改。这允许我们在不实际知道值的情况下触发失效事件。该值将在访问之前进行评估。
因此,简单来说,如果您需要知道可观察对象的新值,请使用ChangeListener,否则使用InvalidationListener。
我可以看到,理论上你可以添加一个更改侦听器onActionProperty,但我认为这不会调用时,按钮被点击,而是如果setOnAction实际更改事件处理程序,附加?
是的,你是对的。要处理按钮单击,您需要使用setOnAction()
。ChangeListener
与事件处理无关。