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 非常慢。当您使用其他操作或限制您正在收听的事件时,不会发生这种情况。
我正在 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 byIntrospector.getBeanInfo(…)
允许您动态发现组件支持哪些事件,即它声明的哪些方法匹配事件源模式。-
EventHandler
class 允许生成侦听器,在事件发生时调用特定的目标方法。它还允许将对事件调用方法的结果作为参数传递给目标方法。此外,如 windowClosing→dispose 示例所示,支持无参数方法和指定特定侦听器方法。 EventHandler
基于Proxy
facility, which allows implementing arbitrary interfaces via a generalInvocationHandler
,除非您想走生成字节码的路线,否则在您的脚本语言上下文中它可能对其他用途非常有用。
请注意,打印所有事件的示例代码可能会使 UI 非常慢。当您使用其他操作或限制您正在收听的事件时,不会发生这种情况。