所有 Swing 组件都是 JavaBeans 组件。它们有一系列的 setter 和 getter 方法,这些方法的类似于 void setXXX(类型名) 和 Type getXXX() 。关于这些方法没有什么特别之处,并且正如所预期的,它们遵循 JavaBeans 的属性命名规范。我们今天要讨论的是JavaBeans 组件的一个方面,即一对监听器方法 addXXXListener (XXXListener name) 和 removeXXXListener (XXXListener name) 。 XXListener 在这里指的是一个监听器对象,它扩展了 EventListener 接口,等候与监听器关联的组件中的各种事件发生。当事件发生时,所有注册的监听器都会得到事件的通知(没有特定的顺序)。通过魔术般的一个小反射(reflection)和一个新的 java.beans.EventHandler 类,您可以将一个监听器附加到一个 bean 上,而无需直接实现这个监听器接口或者创建那些烦人的小匿名内部类。
以前的方法
在深入到使用新的 EventHandler 类的细节之前,让我们回顾一下不使用这个类时是如何进行工作的。我们举一个对 Swing 框架中的按钮选择做出响应的简单例子。选择一个按钮生成一个 ActionEvent 。要对这个事件做出响应,需要将 ActionListener 附加到这个按钮上,如清单 1 所示:
清单 1. 监听标准按钮选择
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class ButtonSelection extends JFrame {
public ButtonSelection() {
super("Selection");
setDefaultCloseOperation(EXIT_ON_CLOSE);
JButton button = new JButton("Pick Me");
Container contentPane = getContentPane();
contentPane.add(button, BorderLayout.CENTER);
button.addActionListener(
new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Hello, World!");
}
}
);
}
public static void main(String args[]) {
JFrame frame = new ButtonSelection();
frame.setSize(200, 100);
frame.show();
}
}
这里没有任何神奇之处,您可能已经熟悉这种代码了。这里, ActionListener 实现是适时定义的,它定义为一个匿名内部类,并直接附加到按钮上。在选择这个按钮时,字符串 Hello, World! 就打印到控制台中。与程序关联的屏幕如图 1 所示:
图 1. 带 ActionListener 的按钮选择
在 JavaBeans 规范中,没有要求您创建匿名内部类进行事件监听。 IDE 工具常常采用这种行为:您说要一个监听器,它就生成一个 stub,然后您填入细节。完成同样工作的其他方式包括在调用类中提供指定的实现或者实现您自己的接口。
定义了每一个实现类后,就会创建一个单独的.class 文件。所以,在前面的 ButtonSelection 程序中,您会看到编译器生成两个 .class 文件:ButtonSelection.class 和 ButtonSelection$1.class。 $1 是 Sun 编译器命名匿名内部类的方式,计数随着每一个类增加。其他编译器可能有不同的命名方式。