模块 java.desktop

类 EventHandler

java.lang.Object
java.beans.EventHandler
所有已实现的接口:
InvocationHandler

public class EventHandler extends Object implements InvocationHandler
EventHandler 类支持动态生成事件监听器,其方法执行涉及传入事件对象和目标对象的简单语句。

EventHandler 类旨在供交互式工具(例如应用程序构建器)使用,这些工具允许开发人员在 bean 之间建立连接。通常,连接是从用户接口 bean(事件 source)到应用程序逻辑 bean(target)。这种最有效的连接将应用程序逻辑与用户接口隔离开来。例如,从 JCheckBox 到接受boolean的方法的连接的 EventHandler 可以处理提取复选框的状态并将其直接传递给方法,以便该方法与用户接口层隔离。

内部类是另一种更通用的处理用户接口事件的方法。 EventHandler 类仅处理使用内部类可能的子集。但是,EventHandler 比内部类更适合长期持久化方案。此外,在多次实现相同接口的大型应用程序中使用 EventHandler 可以减少应用程序的磁盘和内存占用。

使用 EventHandler 创建的监听器占用空间如此之小的原因是 EventHandler 所依赖的 Proxy 类共享相同接口的实现。例如,如果您使用 EventHandler create 方法在应用程序中生成所有 ActionListener ,则所有动作监听器都将是单个类(由 Proxy 类创建)的实例。通常,基于 Proxy 类的监听器需要为每个 listener type(接口)创建一个监听器类,而内部类方法需要为每个 listener(实现该接口的对象)创建一个类。

您通常不会直接处理 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 接口的新实现并将其实例添加到按钮,可以获得相同的效果,并增加一些编译时类型安全性:
//Equivalent code using an inner class instead of EventHandler.
myButton.addActionListener(new ActionListener() {
  public void actionPerformed(ActionEvent e) {
    frame.toFront();
  }
});
EventHandler 的下一个最简单的用法是从监听器接口(通常是事件对象)中的方法的第一个参数中提取属性值,并使用它来设置目标对象中的属性值。在下面的示例中,我们创建了一个 ActionListener,它将目标 (myButton) 对象的 nextFocusableComponent 属性设置为事件的“源”属性的值。
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 最常见的用途可能是从事件对象的 source 中提取属性值,并将此值设置为目标对象的属性值。在下面的示例中,我们创建了一个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 将根据源调用适当的方法。如果源为空,则任一方法都适用,调用的方法未定义。出于这个原因,我们建议不要针对重载方法。
自从:
1.4
参见:
  • 构造方法总结

    构造方法
    构造方法
    描述
    EventHandler(Object target, String action, String eventPropertyName, String listenerMethodName)
    创建一个新的 EventHandler 对象;您通常使用 create 方法之一而不是直接调用此构造函数。
  • 方法总结

    修饰符和类型
    方法
    描述
    static <T> T
    create(Class<T> listenerInterface, Object target, String action)
    创建 listenerInterface 的实现,其中监听器接口中的 all 方法将处理程序的 action 应用到 target
    static <T> T
    create(Class<T> listenerInterface, Object target, String action, String eventPropertyName)
    /** 创建 listenerInterface 的实现,其中 all 方法将事件表达式 eventPropertyName 的值传递给语句中的最终方法 action,该方法应用于 target
    static <T> T
    create(Class<T> listenerInterface, Object target, String action, String eventPropertyName, String listenerMethodName)
    创建 listenerInterface 的实现,其中名为 listenerMethodName 的方法将事件表达式 eventPropertyName 的值传递给语句中的最终方法 action,该方法应用于 target
    返回此事件处理程序将设置的目标的可写属性的名称,或此事件处理程序将在目标上调用的方法的名称。
    返回应该在应用于目标的操作中使用的事件的属性。
    返回将触发操作的方法的名称。
    返回此事件处理程序将向其发送消息的对象。
    invoke(Object proxy, Method method, Object[] arguments)
    从事件中提取适当的属性值并将其传递给与此 EventHandler 关联的操作。

    在类 java.lang.Object 中声明的方法

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • 构造方法详细信息

  • 方法详情

    • getTarget

      public Object  getTarget()
      返回此事件处理程序将向其发送消息的对象。
      返回:
      此事件处理程序的目标
      参见:
    • getAction

      public String  getAction()
      返回此事件处理程序将设置的目标的可写属性的名称,或此事件处理程序将在目标上调用的方法的名称。
      返回:
      此事件处理程序的操作
      参见:
    • getEventPropertyName

      public String  getEventPropertyName()
      返回应该在应用于目标的操作中使用的事件的属性。
      返回:
      事件的属性
      参见:
    • getListenerMethodName

      public String  getListenerMethodName()
      返回将触发操作的方法的名称。 null 的返回值表示监听器接口中的所有方法都会触发该操作。
      返回:
      将触发操作的方法的名称
      参见:
    • invoke

      public Object  invoke(Object  proxy, Method  method, Object [] arguments)
      从事件中提取适当的属性值并将其传递给与此 EventHandler 关联的操作。
      指定者:
      invoke 在接口 InvocationHandler
      参数:
      proxy - 代理对象
      method - 监听器接口中的方法
      arguments - 包含在代理实例的方法调用中传递的参数值的对象数组,或者 null 如果接口方法不带参数。原始类型的参数包装在适当的原始包装类的实例中,例如 java.lang.Integerjava.lang.Boolean
      返回:
      将操作应用于目标的结果
      参见:
    • create

      public static <T> T create(Class <T> listenerInterface, Object  target, String  action)
      创建 listenerInterface 的实现,其中监听器接口中的 all 方法将处理程序的 action 应用到 target 。此方法是通过调用 create 方法的另一个更通用的实现来实现的,其中 eventPropertyNamelistenerMethodName 都取值 null 。有关 action 参数的完整说明,请参阅 the general version of create

      要创建一个显示 JDialogdialog.show()ActionListener,可以这样写:

      EventHandler.create(ActionListener.class, dialog, "show")
      
      类型参数:
      T - 要创建的类型
      参数:
      listenerInterface - 为其创建代理的监听器接口
      target - 将执行操作的对象
      action - 目标上的(可能限定的)属性或方法的名称
      返回:
      实现 listenerInterface 的对象
      抛出:
      NullPointerException - 如果 listenerInterface 为空
      NullPointerException - 如果 target 为空
      NullPointerException - 如果 action 为空
      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 的实现,其中 all 方法将事件表达式 eventPropertyName 的值传递给语句中的最终方法 action,该方法应用于 target。此方法是通过调用更通用的 create 方法实现的,其中 listenerMethodName 取值 null 。有关 actioneventPropertyName 参数的完整说明,请参阅 the general version of create

      要创建将 JLabel 的文本设置为传入事件的 JTextField 源的文本值的 ActionListener,您可以使用以下代码:

      EventHandler.create(ActionListener.class, label, "text", "source.text");
      
      这等效于以下代码:
      //Equivalent code using an inner class instead of EventHandler.
      new ActionListener() {
        public void actionPerformed(ActionEvent event) {
          label.setText(((JTextField)(event.getSource())).getText());
         }
      };
      
      类型参数:
      T - 要创建的类型
      参数:
      listenerInterface - 为其创建代理的监听器接口
      target - 将执行操作的对象
      action - 目标上的(可能限定的)属性或方法的名称
      eventPropertyName - 传入事件的可读属性的(可能是合格的)名称
      返回:
      实现 listenerInterface 的对象
      抛出:
      NullPointerException - 如果 listenerInterface 为空
      NullPointerException - 如果 target 为空
      NullPointerException - 如果 action 为空
      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 中提取“文本”属性,请使用以下任何一个作为 eventPropertyName"source.text""getSource.text" "getSource.getText""source.getText"。如果找不到方法,或者在调用方法的过程中产生异常,将在调度时抛出 RuntimeException。例如,如果传入事件对象为 null,并且 eventPropertyName 非空且不为空,则将抛出 RuntimeException

      action 参数与 eventPropertyName 参数的格式相同,其中最后一个属性名称标识方法名称或可写属性。

      如果 listenerMethodNamenull all 接口中的方法触发 actiontarget 上执行。

      例如,要创建一个 MouseListener,它在每次按下鼠标按钮时将目标对象的 origin 属性设置为传入的 MouseEvent 的位置(即 mouseEvent.getPoint() 的值),可以这样写:

      EventHandler.create(MouseListener.class, target, "origin", "point", "mousePressed");
      
      这相当于编写一个 MouseListener,其中除了 mousePressed 之外的所有方法都是空操作:
      //Equivalent code using an inner class instead of EventHandler.
      new MouseAdapter() {
        public void mousePressed(MouseEvent e) {
          target.setOrigin(e.getPoint());
        }
      };
       
      类型参数:
      T - 要创建的类型
      参数:
      listenerInterface - 为其创建代理的监听器接口
      target - 将执行操作的对象
      action - 目标上的(可能限定的)属性或方法的名称
      eventPropertyName - 传入事件的可读属性的(可能是合格的)名称
      listenerMethodName - 应触发操作的监听器接口中的方法名称
      返回:
      实现 listenerInterface 的对象
      抛出:
      NullPointerException - 如果 listenerInterface 为空
      NullPointerException - 如果 target 为空
      NullPointerException - 如果 action 为空
      IllegalArgumentException - 如果为 listenerInterface 创建代理因 Proxy.newProxyInstance(java.lang.ClassLoader, java.lang.Class<?>[], java.lang.reflect.InvocationHandler) 指定的任何限制而失败
      参见: