- 所有已实现的接口:
-
InvocationHandler
EventHandler
类提供了支持,用于动态生成事件监听器,其方法执行涉及传入事件对象和目标对象的简单语句。
EventHandler
类旨在被交互式工具使用,例如应用程序构建器,允许开发人员在bean之间建立连接。通常,连接是从用户界面bean(事件源)到应用程序逻辑bean(目标)的。这种类型的最有效连接将应用程序逻辑与用户界面隔离开来。例如,连接从JCheckBox
到接受布尔值的方法的EventHandler
可以处理提取复选框状态并直接传递给方法,使方法与用户界面层隔离开来。
内部类是另一种更一般的处理用户界面事件的方式。 EventHandler
类仅处理内部类可能实现的一部分功能。但是,与内部类相比,EventHandler
在长期持久性方案中的效果更好。此外,在实现同一接口多次的大型应用程序中使用EventHandler
可以减少应用程序的磁盘和内存占用。
使用EventHandler
创建的监听器具有很小的占用空间的原因是EventHandler
依赖的Proxy
类共享相同接口的实现。例如,如果您使用EventHandler create
方法创建应用程序中的所有ActionListener
,则所有动作监听器将是单个类的实例(由Proxy
类创建)。通常,基于Proxy
类的监听器需要为每个监听器类型(接口)创建一个监听器类,而内部类方法则需要为每个监听器(实现接口的对象)创建一个类。
通常不直接处理EventHandler
实例。相反,您可以使用EventHandler
的create
方法之一来创建实现给定监听器接口的对象。此监听器对象在幕后使用EventHandler
对象来封装有关事件、在事件发生时要发送消息的对象、要发送的消息(方法)以及方法的任何参数的信息。以下部分提供了使用create
方法创建监听器对象的示例。
使用 EventHandler 的示例
EventHandler
的最简单用法是安装一个调用目标对象上不带参数的方法的监听器。在以下示例中,我们创建一个ActionListener
,它调用javax.swing.JFrame
实例上的toFront
方法。
当按下myButton.addActionListener( (ActionListener)EventHandler.create(ActionListener.class, frame, "toFront"));
myButton
时,将执行语句frame.toFront()
。通过定义ActionListener
接口的新实现并将其实例添加到按钮,也可以获得相同效果,同时增加一些编译时类型安全性:
//使用内部类而不是 EventHandler 的等效代码。 myButton.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { frame.toFront(); } });
EventHandler
的下一个最简单用法是从监听器接口中方法的第一个参数(通常是事件对象)中提取属性值,并将其用于设置目标对象的属性值。在以下示例中,我们创建一个ActionListener
,将目标对象(myButton)的nextFocusableComponent
属性设置为事件的“source”属性的值。
这对应于以下内部类实现:EventHandler.create(ActionListener.class, myButton, "nextFocusableComponent", "source")
还可以创建一个//使用内部类而不是 EventHandler 的等效代码。 new ActionListener() { public void actionPerformed(ActionEvent e) { myButton.setNextFocusableComponent((Component)e.getSource()); } }
EventHandler
,只是将传入的事件对象传递给目标的操作。如果第四个EventHandler.create
参数是空字符串,则事件将只是传递:
这对应于以下内部类实现:EventHandler.create(ActionListener.class, target, "doActionEvent", "")
//使用内部类而不是 EventHandler 的等效代码。 new ActionListener() { public void actionPerformed(ActionEvent e) { target.doActionEvent(e); } }
EventHandler
最常见的用法可能是从事件对象的source中提取属性值,并将此值设置为目标对象的属性值。在以下示例中,我们创建一个ActionListener
,将目标对象的“label”属性设置为事件的“source”属性的“text”属性的值。
这对应于以下内部类实现:EventHandler.create(ActionListener.class, myButton, "label", "source.text")
事件属性可以用任意数量的使用"."字符分隔的属性前缀进行“限定”。出现在“.”字符之前的“限定”名称被视为应该应用于事件对象的属性名称,从最左边开始应用。//使用内部类而不是 EventHandler 的等效代码。 new ActionListener { public void actionPerformed(ActionEvent e) { myButton.setLabel(((JTextField)e.getSource()).getText()); } }
例如,以下动作监听器
可以写成以下内部类(假设所有属性都有规范的getter方法并返回适当的类型):EventHandler.create(ActionListener.class, target, "a", "b.c.d")
目标属性也可以用任意数量的使用"."字符分隔的属性前缀进行“限定”。例如,以下动作监听器://使用内部类而不是 EventHandler 的等效代码。 new ActionListener { public void actionPerformed(ActionEvent e) { target.setA(e.getB().getC().isD()); } }
EventHandler.create(ActionListener.class, target, "a.b", "c.d")可以写成以下内部类(假设所有属性都有规范的getter方法并返回适当的类型):
//使用内部类而不是 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,则两种方法都适用,调用的方法是未定义的。因此,我们建议不要针对重载方法。
- 自 JDK 1.4 起:
- 1.4
- 参见:
-
Constructor Summary
ConstructorDescriptionEventHandler
(Object target, String action, String eventPropertyName, String listenerMethodName) 创建一个新的EventHandler
对象;通常使用create
方法之一来创建对象,而不是直接调用此构造函数。 -
Method Summary
Modifier and TypeMethodDescriptionstatic <T> T
创建listenerInterface
的实现,其中监听器接口中的所有方法都将处理程序的action
应用于target
。static <T> T
/** 创建listenerInterface
的实现,其中所有方法都将事件表达式eventPropertyName
的值传递给语句的最终方法action
,该方法应用于target
。static <T> T
create
(Class<T> listenerInterface, Object target, String action, String eventPropertyName, String listenerMethodName) 创建listenerInterface
的实现,其中名为listenerMethodName
的方法将事件表达式eventPropertyName
的值传递给语句的最终方法action
,该方法应用于target
。返回此事件处理程序将设置的目标可写属性的名称,或将在目标上调用的方法的名称。返回应在应用于目标的操作中使用的事件属性。返回将触发操作的方法的名称。返回将发送消息给此事件处理程序的对象。从事件中提取适当的属性值并将其传递给与此EventHandler
关联的操作。
-
Constructor Details
-
EventHandler
@ConstructorProperties({"target","action","eventPropertyName","listenerMethodName"}) public EventHandler(Object target, String action, String eventPropertyName, String listenerMethodName) 创建一个新的EventHandler
对象;通常使用create
方法之一来创建对象,而不是直接调用此构造函数。有关eventPropertyName
和listenerMethodName
参数的完整描述,请参阅create的通用版本
。- 参数:
-
target
- 将执行操作的对象 -
action
- 目标上的属性或方法的名称(可能带限定符) -
eventPropertyName
- 传入事件的可读属性的名称(可能带限定符) -
listenerMethodName
- 监听器接口中应触发操作的方法的名称 - 抛出:
-
NullPointerException
- 如果target
为null -
NullPointerException
- 如果action
为null - 参见:
-
-
Method Details
-
getTarget
返回此事件处理程序将发送消息的对象。- 返回:
- 此事件处理程序的目标
- 参见:
-
getAction
返回此事件处理程序将设置的目标的可写属性的名称,或者此事件处理程序将在目标上调用的方法的名称。- 返回:
- 此事件处理程序的操作
- 参见:
-
getEventPropertyName
返回应用于目标的操作中应使用的事件的属性。- 返回:
- 事件的属性
- 参见:
-
getListenerMethodName
返回将触发操作的方法的名称。返回值null
表示监听器接口中的所有方法都会触发操作。- 返回:
- 将触发操作的方法的名称
- 参见:
-
invoke
从事件中提取适当的属性值并将其传递给与此EventHandler
关联的操作。- 指定者:
-
invoke
在接口中InvocationHandler
- 参数:
-
proxy
- 代理对象 -
method
- 监听器接口中的方法 -
arguments
- 包含在代理实例上的方法调用中传递的参数值的对象数组,如果接口方法不带参数,则为null
。基本类型的参数将包装在适当的基本包装类的实例中,例如java.lang.Integer
或java.lang.Boolean
。 - 返回:
- 将操作应用于目标的结果
- 参见:
-
create
创建listenerInterface
的实现,其中监听器接口中的所有方法都将将处理程序的action
应用于target
。通过调用另一个更通用的create
方法来实现此方法,其中eventPropertyName
和listenerMethodName
都取值null
。有关action
参数的完整描述,请参阅create的通用版本
。要创建一个显示
JDialog
并使用dialog.show()
的ActionListener
,可以编写以下代码:EventHandler.create(ActionListener.class, dialog, "show")
- 类型参数:
-
T
- 要创建的类型 - 参数:
-
listenerInterface
- 要为其创建代理的监听器接口 -
target
- 将执行操作的对象 -
action
- 目标上的属性或方法的名称(可能带限定符) - 返回:
-
实现
listenerInterface
的对象 - 抛出:
-
NullPointerException
- 如果listenerInterface
为null -
NullPointerException
- 如果target
为null -
NullPointerException
- 如果action
为null -
IllegalArgumentException
- 如果为listenerInterface
创建代理失败,原因是由Proxy.newProxyInstance(java.lang.ClassLoader, java.lang.Class<?>[], java.lang.reflect.InvocationHandler)
指定的任何限制 - 参见:
-
create
public static <T> T create(Class<T> listenerInterface, Object target, String action, String eventPropertyName) /** 创建listenerInterface
的实现,其中监听器接口中的所有方法都将传递事件表达式eventPropertyName
的值到语句的最终方法action
中,该方法应用于target
。通过调用更通用的create
方法来实现此方法,其中listenerMethodName
取值null
。有关action
和eventPropertyName
参数的完整描述,请参阅create的通用版本
。要创建一个将
JLabel
的文本设置为传入事件的JTextField
源的文本值的ActionListener
,可以使用以下代码:EventHandler.create(ActionListener.class, label, "text", "source.text");
//使用内部类而不是EventHandler的等效代码。 new ActionListener() { public void actionPerformed(ActionEvent event) { label.setText(((JTextField)(event.getSource())).getText()); } };
- 类型参数:
-
T
- 要创建的类型 - 参数:
-
listenerInterface
- 要为其创建代理的监听器接口 -
target
- 将执行操作的对象 -
action
- 目标上的属性或方法的名称(可能带限定符) -
eventPropertyName
- 传入事件的可读属性的名称(可能带限定符) - 返回:
-
实现
listenerInterface
的对象 - 抛出:
-
NullPointerException
- 如果listenerInterface
为null -
NullPointerException
- 如果target
为null -
NullPointerException
- 如果action
为null -
IllegalArgumentException
- 如果为listenerInterface
创建代理失败,原因是由Proxy.newProxyInstance(java.lang.ClassLoader, java.lang.Class<?>[], java.lang.reflect.InvocationHandler)
指定的任何限制 - 参见:
-
create
public static <T> T create(Class<T> listenerInterface, Object target, String action, String eventPropertyName, String listenerMethodName) 创建一个listenerInterface
的实现,其中名为listenerMethodName
的方法将事件表达式eventPropertyName
的值传递给语句中的最终方法action
,该方法应用于target
。所有其他监听器方法均不执行任何操作。eventPropertyName
字符串用于从传递给目标方法的传入事件对象中提取值。常见情况是目标方法不接受参数,在这种情况下,应该对eventPropertyName
使用null值。或者,如果希望将传入的事件对象直接传递给目标方法,请使用空字符串。eventPropertyName
字符串的格式是一系列方法或属性,其中每个方法或属性应用于从传入事件对象开始返回的前一个方法的值。语法是:propertyName{.propertyName}*
,其中propertyName
匹配方法或属性。例如,要从MouseEvent
中提取point
属性,可以将"point"
或"getPoint"
用作eventPropertyName
。要从具有JLabel
源的MouseEvent
中提取"text"属性,可以将以下任何内容用作eventPropertyName
:"source.text"
,"getSource.text"
,"getSource.getText"
或"source.getText"
。如果找不到方法,或者在调用方法时生成异常,将在调度时抛出RuntimeException
。例如,如果传入的事件对象为null,并且eventPropertyName
非null且不为空,则将抛出RuntimeException
。action
参数与eventPropertyName
参数的格式相同,其中最后一个属性名称标识方法名或可写属性。如果
listenerMethodName
为null
,则接口中的所有方法都会触发在target
上执行action
。例如,要创建一个
MouseListener
,每次按下鼠标按钮时将目标对象的origin
属性设置为传入MouseEvent
的位置(即mouseEvent.getPoint()
的值),可以编写如下代码:EventHandler.create(MouseListener.class, target, "origin", "point", "mousePressed");
MouseListener
,其中除了mousePressed
之外的所有方法都是空操作://相当于使用内部类而不是EventHandler编写的等效代码。 new MouseAdapter() { public void mousePressed(MouseEvent e) { target.setOrigin(e.getPoint()); } };
- 类型参数:
-
T
- 要创建的类型 - 参数:
-
listenerInterface
- 要为其创建代理的监听器接口 -
target
- 将执行操作的对象 -
action
- 目标上的(可能限定的)属性或方法的名称 -
eventPropertyName
- 传入事件的可读属性的(可能限定的)名称 -
listenerMethodName
- 应触发操作的监听器接口中的方法的名称 - 返回:
-
实现
listenerInterface
的对象 - 抛出:
-
NullPointerException
- 如果listenerInterface
为null -
NullPointerException
- 如果target
为null -
NullPointerException
- 如果action
为null -
IllegalArgumentException
- 如果为listenerInterface
创建代理失败,因为未满足Proxy.newProxyInstance(java.lang.ClassLoader, java.lang.Class<?>[], java.lang.reflect.InvocationHandler)
指定的任何限制 - 参见:
-