EventHandler类为动态生成事件侦听器提供支持,其方法执行涉及传入事件对象和目标对象的简单语句。
EventHandler类旨在供交互式工具(如应用程序构建器)使用,这些工具允许开发人员在bean之间建立连接。 通常,连接是从用户界面bean(事件源 )到应用程序逻辑bean( 目标 )。 这种最有效的连接将应用程序逻辑与用户界面隔离开来。 例如, EventHandler用于从JCheckBox到接受布尔值的方法的连接可以处理提取复选框的状态并将其直接传递给方法,以便该方法与用户界面层隔离。
内部类是处理来自用户界面的事件的另一种更通用的方法。 EventHandler类仅处理使用内部类可能的子集。 但是, EventHandler对于长期持久性方案比内部类更好。 此外,在大型应用程序中使用EventHandler ,其中多次实现相同的接口可以减少应用程序的磁盘和内存占用。
使用EventHandler创建的侦听EventHandler具有如此小的占用空间的原因是EventHandler依赖的Proxy类共享相同接口的实现。 例如,如果使用EventHandler create方法在应用程序中生成所有ActionListener ,则所有动作侦听器都将是单个类的实例(一个由Proxy类创建)。 通常,基于Proxy类的侦听器需要为每个侦听器类型 (接口)创建一个侦听器类,而内部类方法需要为每个侦听器 (实现接口的对象)创建一个类。
您通常不直接处理EventHandler实例。 而是使用EventHandler create方法之一来创建实现给定侦听器接口的对象。 此侦听器对象在EventHandler使用EventHandler对象来封装有关事件的信息,事件发生时要发送消息的对象,要发送的消息(方法)以及方法的任何参数。 以下部分提供了如何使用create方法创建侦听器对象的create 。
使用EventHandler的示例
EventHandler的最简单用法是安装一个监听器,该监听器在没有参数的情况下调用目标对象上的方法。
在下面的例子中,我们创建ActionListener调用该toFront上的一个实例方法javax.swing.JFrame 。
myButton.addActionListener(
(ActionListener)EventHandler.create(ActionListener.class, frame, "toFront"));
当myButton被按下时,声明frame.toFront()将被执行。
通过定义ActionListener接口的新实现并将其实例添加到按钮,可以获得相同的效果,并具有一些额外的编译时类型安全性:
//Equivalent code using an inner class instead of EventHandler.
myButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
frame.toFront();
}
});
EventHandler的下一个最简单用法是从侦听器接口中的方法的第一个参数(通常是事件对象)中提取属性值,并使用它来设置目标对象中属性的值。
在下面的示例中,我们创建了一个ActionListener , nextFocusableComponent目标(myButton)对象的nextFocusableComponent属性设置为事件的“source”属性的值。
EventHandler.create(ActionListener.class, myButton, "nextFocusableComponent", "source")
这将对应于以下内部类实现:
//Equivalent code using an inner class instead of EventHandler.
new ActionListener() {
public void actionPerformed(ActionEvent e) {
myButton.setNextFocusableComponent((Component)e.getSource());
}
}
也可以创建一个EventHandler ,它只是将传入的事件对象传递给目标的动作。
如果第四个EventHandler.create参数是一个空字符串,那么该事件只是传递:
EventHandler.create(ActionListener.class, target, "doActionEvent", "")
这将对应于以下内部类实现:
//Equivalent code using an inner class instead of EventHandler.
new ActionListener() {
public void actionPerformed(ActionEvent e) {
target.doActionEvent(e);
}
}
EventHandler最常见的用法可能是从事件对象的源中提取属性值,并将此值设置为目标对象的属性值。
在下面的示例中,我们创建了一个ActionListener ,它将目标对象的“label”属性设置为事件源的“text”属性值(“source”属性的值)。
EventHandler.create(ActionListener.class, myButton, "label", "source.text")
这将对应于以下内部类实现:
//Equivalent code using an inner class instead of EventHandler.
new ActionListener {
public void actionPerformed(ActionEvent e) {
myButton.setLabel(((JTextField)e.getSource()).getText());
}
}
事件属性可以“限定”,其中任意数量的属性前缀用“。”分隔。
字符。
出现在“。”之前的“合格”名称。
将字符作为应该应用的属性的名称,最左边的应用于事件对象。
例如,以下动作侦听器
EventHandler.create(ActionListener.class, target, "a", "b.c.d")
可能被编写为以下内部类(假设所有属性都具有规范的getter方法并返回适当的类型):
//Equivalent code using an inner class instead of EventHandler.
new ActionListener {
public void actionPerformed(ActionEvent e) {
target.setA(e.getB().getC().isD());
}
}
目标属性也可以“限定”,其中任意数量的属性前缀用“。”分隔。
字符。
例如,以下动作侦听器:
EventHandler.create(ActionListener.class, target, "a.b", "c.d")
可能被编写为以下内部类(假设所有属性都具有规范的getter方法并返回适当的类型):
//Equivalent code using an inner class instead of EventHandler.
new ActionListener {
public void actionPerformed(ActionEvent e) {
target.getA().setB(e.getC().isD());
}
}
由于EventHandler最终依赖于反射来调用方法,因此我们建议不要使用重载方法。 例如,如果目标是类MyTarget的实例,其定义为:
public class MyTarget {
public void doIt(String);
public void doIt(Object);
}
然后方法doIt过载。
EventHandler将根据源调用适当的方法。
如果源为null,则任一方法都是合适的,并且调用的方法是未定义的。
出于这个原因,我们建议不要针对重载方法。