- 写在前面的话
- 引言
- 第 1 章 对象入门
- 第 2 章 一切都是对象
- 第 3 章 控制程序流程
- 第 4 章 初始化和清除
- 第 5 章 隐藏实施过程
- 第 6 章 类再生
- 第 7 章 多形性
- 第 8 章 对象的容纳
- 第 9 章 违例差错控制
- 第 10 章 Java IO 系统
- 第 11 章 运行期类型鉴定
- 第 12 章 传递和返回对象
- 第 十三 章 创建窗口和程序片
- 第 14 章 多线程
- 第 15 章 网络编程
- 第 16 章 设计范式
- 第 17 章 项目
- 附录 A 使用非 JAVA 代码
- 附录 B 对比 C++和 Java
- 附录 C Java 编程规则
- 附录 D 性能
- 附录 E 关于垃圾收集的一些话
- 附录 F 推荐读物
13.16.2 事件和接收者类型
所有 AWT 组件都被改变成包含 addXXXListener() 和 removeXXXListener() 方法,因此特定的接收器类型可从每个组件中增加和删除。我们会注意到“XXX”在每个场合中同样表示自变量的方法,例如,addFooListener(FooListener fl)。下面这张表格总结了通过提供 addXXXListener() 和 removeXXXListener() 方法,从而支持那些特定事件的相关事件、接收器、方法以及组件。
事件,接收器接口及添加和删除方法 支持这个事件的组件
Event, listener interface and add- and remove-methods | Components supporting this event |
---|---|
ActionEvent | Button , List , TextField, MenuItem, and its derivatives including CheckboxMenuItem , Menu, and PopupMenu |
AdjustmentEvent | Scrollbar |
ComponentEvent | Component and its derivatives, including Button , Canvas , Checkbox , Choice , Container , Panel , Applet , ScrollPane , Window , Dialog , FileDialog, Frame , Label , List , Scrollbar , TextArea, and TextField |
ContainerEvent | Container and its derivatives, including Panel , Applet , ScrollPane , Window , Dialog , FileDialog, and Frame |
FocusEvent | Component and its derivatives, including Button , Canvas , Checkbox , Choice , Container , Panel , Applet , ScrollPane , Window , Dialog , FileDialog, Frame Label , List , Scrollbar , TextArea, and TextField |
KeyEvent | Component and its derivatives, including Button , Canvas , Checkbox , Choice , Container , Panel , Applet , ScrollPane , Window , Dialog , FileDialog, Frame , Label , List , Scrollbar , TextArea, and TextField |
MouseEvent (for both clicks and motion) | Component and its derivatives, including Button , Canvas , Checkbox , Choice , Container , Panel , Applet , ScrollPane , Window , Dialog , FileDialog, Frame , Label , List , Scrollbar , TextArea, and TextField |
MouseEvent[55] (for both clicks and motion) | Component and its derivatives, including Button , Canvas , Checkbox , Choice , Container , Panel , Applet , ScrollPane , Window , Dialog , FileDialog, Frame , Label , List , Scrollbar , TextArea, and TextField |
WindowEvent | Window and its derivatives, including Dialog , FileDialog, and Frame |
ItemEvent | Checkbox , CheckboxMenuItem , Choice , List, and anything that implements the ItemSelectable interface |
TextEvent | Anything derived from TextComponent , including TextArea and TextField |
⑤:即使表面上如此,但实际上并没有 MouseMotiionEvent(鼠标运动事件)。单击和运动都合成到 MouseEvent 里,所以 MouseEvent 在表格中的这种另类行为并非一个错误。
可以看到,每种类型的组件只为特定类型的事件提供了支持。这有助于我们发现由每种组件支持的事件,如下表所示:
组件类型 支持的事件
Component type | Events supported by this component |
---|---|
Adjustable | AdjustmentEvent |
Applet | ContainerEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent |
Button | ActionEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent |
Canvas | FocusEvent, KeyEvent, MouseEvent, ComponentEvent |
Checkbox | ItemEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent |
CheckboxMenuItem | ActionEvent, ItemEvent |
Choice | ItemEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent |
Component | FocusEvent, KeyEvent, MouseEvent, ComponentEvent |
Container | ContainerEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent |
Dialog | ContainerEvent, WindowEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent |
FileDialog | ContainerEvent, WindowEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent |
Frame | ContainerEvent, WindowEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent |
Label | FocusEvent, KeyEvent, MouseEvent, ComponentEvent |
List | ActionEvent, FocusEvent, KeyEvent, MouseEvent, ItemEvent, ComponentEvent |
Menu | ActionEvent |
MenuItem | ActionEvent |
Panel | ContainerEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent |
PopupMenu | ActionEvent |
Scrollbar | AdjustmentEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent |
ScrollPane | ContainerEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent |
TextArea | TextEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent |
TextComponent | TextEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent |
TextField | ActionEvent, TextEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent |
Window | ContainerEvent, WindowEvent, FocusEvent, KeyEvent, MouseEvent, ComponentEvent |
一旦知道了一个特定的组件支持哪些事件,就不必再去寻找任何东西来响应那个事件。只需简单地:
(1) 取得事件类的名字,并删掉其中的“Event”字样。在剩下的部分加入“Listener”字样。这就是在我们的内部类里需要实现的接收器接口。
(2) 实现上面的接口,针对想要捕获的事件编写方法代码。例如,假设我们想捕获鼠标的移动,所以需要为 MouseMotiionListener 接口的 mouseMoved() 方法编写代(当然还必须实现其他一些方法,但这里有捷径可循,马上就会讲到这个问题)。
(3) 为步骤 2 中的接收器类创建一个对象。随自己的组件和方法完成对它的注册,方法是在接收器的名字里加入一个前缀“add”。比如 addMouseMotionListener()。
下表是对接收器接口的一个总结:
接收器接口 接口中的方法
Listener interface | Methods in interface |
---|---|
ActionListener | actionPerformed(ActionEvent) |
AdjustmentListener | adjustmentValueChanged( |
ComponentListener | componentHidden(ComponentEvent) |
ContainerListener | componentAdded(ContainerEvent) |
FocusListener | focusGained(FocusEvent) |
KeyListener | keyPressed(KeyEvent) |
MouseListener | mouseClicked(MouseEvent) |
MouseMotionListener | mouseDragged(MouseEvent) |
WindowListener | windowOpened(WindowEvent) |
ItemListener | itemStateChanged(ItemEvent) |
TextListener | textValueChanged(TextEvent) |
1. 用接收器适配器简化操作
在上面的表格中,我们可以注意到一些接收器接口只有唯一的一个方法。它们的执行是无轻重的,因为我们仅当需要书写特殊方法时才会执行它们。然而,接收器接口拥有多个方法,使用起来却不太友好。例如,我们必须一直运行某些事物,当我们创建一个应用程序时对帧提供一个 WindowListener,以便当我们得到 windowClosing() 事件时可以调用 System.exit(0) 以退出应用程序。但因为 WindowListener 是一个接口,我们必须执行其它所有的方法即使它们不运行任何事件。这真令人讨厌。
为了解决这个问题,每个拥有超过一个方法的接收器接口都可拥有适配器,它们的名我们可以在上面的表格中看到。每个适配器为每个接口方法提供默认的方法。(WindowAdapter 的默认方法不是 windowClosing(),而是 System.exit(0) 方法。)此外我们所要做的就是从适配器处继承并过载唯一的需要变更的方法。例如,典型的 WindowListener 我们会像下面这样的使用。
class MyWindowListener extends WindowAdapter { public void windowClosing(WindowEvent e) { System.exit(0); } }
适配器的全部宗旨就是使接收器的创建变得更加简便。
但所谓的“适配器”也有一个缺点,而且较难发觉。假定我们象上面那样写一个 WindowAdapter:
class MyWindowListener extends WindowAdapter { public void WindowClosing(WindowEvent e) { System.exit(0); } }
表面上一切正常,但实际没有任何效果。每个事件的编译和运行都很正常——只是关闭窗口不会退出程序。您注意到问题在哪里吗?在方法的名字里:是 WindowClosing(),而不是 windowClosing()。大小写的一个简单失误就会造成一个崭新的方法。但是,这并非我们关闭窗口时调用的方法,所以当然没有任何效果。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论