11.5.2 事件和事件监听器
11.5.2 事件和事件监听器
从图11.20中可以看出,当外部动作在AWT
组件上进行操作时,系统会自动生成事件对象,这个事件对象是EventObject
子类的实例,该事件对象会触发注册到事件源上的事件监听器。
AWT
事件机制涉及三个成员: 事件源、事件和事件监听器,其中事件源最容易创建,只要通过new
来创建一个AWT
组件,该组件就是事件源;事件是由系统自动产生的,无须程序员关心。所以,实现事件监听器是整个事件处理的核心。
事件监听器必须实现事件监听器接口,AWT
提供了大量的事件监听器接口用于实现不同类型的事件监听器,用于监听不同类型的事件。AWT
中提供了丰富的事件类,用于封装不同组件上所发生的特定操作—AWT
的事件类都是AWTEvent
类的子类,AWTEvent
是EventObject
的子类。
EventObject
类代表更广义的事件对象,包括Swing
组件上所触发的事件、数据库连接所触发的事件等
AWT事件分类
AWT
事件分为两大类:
低级事件和高级事件
1. 低级事件
低级事件是指基于特定动作的事件。比如进入、点击、拖放等动作的鼠标事件,当组件得到焦点、失去焦点时触发焦点事件。
事件 | 描述 |
---|---|
ComponentEvent |
组件事件,当组件尺寸发生变化、位置发生移动、显示/隐藏状态发生改变时触发该事件。 |
ContainerEvent |
容器事件,当容器里发生添加组件、删除组件时触发该事件。 |
WindowEvent |
窗口事件,当窗口状态发生改变(如打开、关闭、最大化、最小化)时触发该事件。 |
FocusEvent |
焦点事件,当组件得到焦点或失去焦点时触发该事件。 |
KeyEvent |
键盘事件,当按键被按下、松开、单击时触发该事件。 |
MouseEvent |
鼠标事件,当进行单击、按下、松开、移动鼠标等动作时触发该事件。 |
PaintEvent |
组件绘制事件,该事件是一个特殊的事件类型,当GUI 组件调用update/paint 方法来呈现自身时触发该事件,PaintEvent 事件并非专用于事件处理模型。 |
2. 高级事件(语义事件)
高级事件是基于语义的事件,它可以不和特定的动作相关联,而依赖于触发此事件的类。比如,在TextField
中按Enter
键会触发ActionEvent
事件,在滑动条上移动滑块会触发AdjustmentEvent
事件,选中项目列表的某一项就会触发ItemEvent
事件。
事件 | 描述 |
---|---|
ActionEvent |
动作事件,当按钮、菜单项被单击,在TextField 中按Enter 键时触发该事件。 |
AdjustmentEvent |
调节事件,在滑动条上移动滑块以调节数值时触发该事件。 |
ItemEvent |
选项事件,当用户选中某项,或取消选中某项时触发该事件。 |
TextEvent |
文本事件,当文本框、文本域里的文本发生改变时触发该事件 |
AWT
事件继承层次图如图11.21所示
图11.21中使用粗线框圈出的那些事件是常用的AWT
事件。对于没有用粗线框圈出的事件,程序员很少使用它们,它们可能被作为事件基类或作为系统内部实现来使用。
不同的事件需要使用不同的监听器监听,不同的监听器需要实现不同的监听器接口,当指定事件发生后,事件监听器就会调用所包含的事件处理器(实例方法)来处理事件。
表11.1 事件、监听器接口和处理器之间的对应关系
事件 | 监听器接口 | 处理器和触发时机 |
---|---|---|
ActionEvent |
ActionListener |
actionPerformed |
AdjustmentEvent |
AdjustmentListener |
adjustmentValueChanged |
ContainerEvent |
Containerlistener |
|
FocusEvent |
FocusListener |
|
ComponentEvent |
ComponentListener |
|
KeyEvent |
KeyListener |
|
MouseEvent |
MouseListener |
|
MouseEvent |
MouseMotionListener |
|
TextEvent |
TextListener |
textValueChanged : 文本组件里的文本发生改变时触发 |
ItemEvent |
ItemListener |
itemStateChanged : 某项被选中或取消选中时触发 |
WindowEvent |
WindowListener |
|
通过表11.1可以大致知道常用组件可能发生哪些事件,以及该事件对应的监听器接口,通过实现该监听器接口就可以实现对应的事件处理器,然后通过addXxxlistener()
方法将事件监听器注册给指定的组件(事件源)。当事件源组件上发生特定事件时,被注册到该组件的事件监听器里的对应方法(事件处理器)将被触发。
ActionListener
、AdjustmentListener
等事件监听器接口只包含一个抽象方法,这种接口也就是前面介绍的函数式接口,因此可用Lambda
表达式来创建监听器对象
事件处理中的事件处理器方法由系统负责调用
实际上,可以如下理解事件处理模型: 当事件源组件上发生事件时,系统将会执行该事件源组件的所有监听器里的对应方法。与前面编程方式不同的是,普通Java
程序里的方法由程序主动调用,事件处理中的事件处理器方法由系统负责调用
程序示例 一个监听器监听多个组件
下面程序示范了一个监听器监听多个组件,一个组件被多个监听器监听的效果
1 | import java.awt.*; |
上面程序中b1
按钮增加了两个事件监听器,当用户单击b1
按钮时,两个监听器的actionPerform()
方法都会被触发;而且f1监听器同时监听b1
、b2
两个按钮,当b1
、b2
任意一个按钮被单击时,fl
监听器的actionPerform()
方法都会被触发。
上面程序中调用了ActionEvent
对象的getActionCommand()
方法,用于获取被单击按钮上的文本。
运行上面程序,分别单击“按钮一”、“按钮二”一次,将看到如图11.2所示的窗口效果
程序示例 窗口监听器 可关闭窗体
下面程序为窗口添加窗口监听器,从而示范窗口监听器的用法,并允许用户单击窗口右上角的“×”按钮来结束程序。
1 | import java.awt.*; |
上面程序详细监听了窗口的每个动作,当用户单击窗口右上角的每个按钮时,程序都会做出相应的响应,当用户单击窗口中的关闭按钮“×”时,程序将正常退出。
事件适配器
大部分时候,程序无须监听窗口的每个动作,只需要为用户单击窗口中的关闭按钮“×”提供响应即可。无须为每个窗口事件提供响应,程序只想重写windowClosing
事件处理器,但因为该监听器实现了WindowListener
接口,实现该接口就不得不实现该接口里的每个抽象方法,这是非常烦琐的事情。为此,AWT
提供了事件适配器。