Java 中的通用 (JComponent) 事件处理?

Generic (JComponent) event handling in Java?

我正在 Java VM 上实现脚本语言。使用反射,我能够动态创建 Java 辅助对象,访问它们的字段并调用它们的方法。但是,我现在对特定事件类型进行了硬编码处理。例如:JScrollBar addAdjustmentListener() 使用 Adjustable 接口,JFrame windowClosing() 使用 WindowAdapter 接口,JButton addActionListener 使用 ActionListener 接口。在脚本语言的事件接收端,用事件数据调用一个匿名函数,带有0、1或2个任意类型的参数。 我的问题是:Java 中是否有一种(反射性的)方式来处理任意事件?一般处理所有 JComponent 子类事件也是一个好的开始。

以下代码可以作为您的起点:

public static void main(String[] args) {
    JFrame f = new JFrame("example");
    listenToAllEvents(f, System.out, "println");
    JButton b = new JButton("click me");
    listenToAllEvents(b, System.out, "println");
    f.getContentPane().add(b, BorderLayout.PAGE_START);
    f.pack();
    f.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
    f.addWindowListener(
        EventHandler.create(WindowListener.class, f, "dispose", null, "windowClosing"));
    f.setVisible(true);
}
static void listenToAllEvents(Object component, Object listener, String method) {
    BeanInfo bi;
    try {
        bi = Introspector.getBeanInfo(component.getClass());
    } catch (IntrospectionException ex) {
        LOGGER.log(Level.SEVERE, null, ex);
        return;
    }
    for(EventSetDescriptor esd: bi.getEventSetDescriptors()) try {
        esd.getAddListenerMethod().invoke(component,
            EventHandler.create(esd.getListenerType(), listener, method, ""));
    } catch(ReflectiveOperationException ex) {
        LOGGER.log(Level.SEVERE, null, ex);
    }
}

重点是

  • BeanInfo returned by Introspector.getBeanInfo(…) 允许您动态发现组件支持哪些事件,即它声明的哪些方法匹配事件源模式。
  • EventHandler class 允许生成侦听器,在事件发生时调用特定的目标方法。它还允许将对事件调用方法的结果作为参数传递给目标方法。此外,如 windowClosing→dispose 示例所示,支持无参数方法和指定特定侦听器方法。
  • EventHandler 基于 Proxy facility, which allows implementing arbitrary interfaces via a general InvocationHandler,除非您想走生成字节码的路线,否则在您的脚本语言上下文中它可能对其他用途非常有用。

请注意,打印所有事件的示例代码可能会使 UI 非常慢。当您使用其他操作或限制您正在收听的事件时,不会发生这种情况。