Java AWT事件
本文最后更新于:2024年3月18日 凌晨
Java AWT事件
事件处理
- 事件处理包括以下3个部分。
- 事件源:发生事件的GUI部件。
- 事件:用户对事件源进行操作触发事件。
- 事件监听者:负责对事件的处理。
事件处理流程
- 下图给出了动作事件处理的各方关系:
-
给事件源对象注册监听者。
- Java的事件处理机制称为委托事件处理,给事件源对象注册监听者就是发生事件时委托监听者处理事件。
-
事件监听者是在事件发生时要对事件进行处理的对象。
- AWT定义了各种类型的事件,每一种事件有相应的事件监听者接口,在接口中描述了处理相应事件应实现的基本行为,若事件类名为XxxEvent,则事件监听接口的命名为
XxxListener
,给部件注册监听者的方法为addXxxListener(XxxListener a)
,例如,按钮动作事件ActionEvent
的监听者接口为ActionListener
,给按钮注册监听者的方法为addActionListener(ActionListener a)
- AWT定义了各种类型的事件,每一种事件有相应的事件监听者接口,在接口中描述了处理相应事件应实现的基本行为,若事件类名为XxxEvent,则事件监听接口的命名为
-
原则上任何实现了
ActionListener
接口的对象,均可以作为按钮的动作事件的监听者,但要注意,选择监听者应当考虑在事件处理方法中能方便地访问相关对象。 -
如果事件处理方法为类的成员方法就可分别访问这些成员变量,由于内嵌类也可方便访问外部类的成员,因此也常用内嵌类或匿名内嵌类的对象作为监听者。
1 |
|
-
给监听者编写事件处理代码。
- 事件监听者的职责是实现事件的处理,监听者实现
ActionListener
接口必须实现接口中定义的所有方法。 - 在
ActionListener
接口中只定义了一个方法,那就是用来完成事件处理的actionPerformed()
方法,该方法中有一个ActionEvent
类型的参数,在方法体中可通过该参数得到事件源对象,然后在方法体中编写具体的事件处理代码。
- 事件监听者的职责是实现事件的处理,监听者实现
-
发生事件时调用监听者的方法进行相关处理。
- 事件源通过注册监听者的动作实现了委托登记,发生事件时就能根据登记去调用监听者的相应方法。
- 以按钮事件源为例,在发生事件时,调用监听者对象的
actionPerformed()
方法,从而完成事件的处理。 - 不难看出,接口在Java的事件处理中起了关键的约束作用,它决定了事件的发生的必定有相应的事件处理方法可供调用。
事件监听者接口及其方法
- 图形界面的每个可能产生事件的部件称为事件源,不同事件源上发生的事件种类不同,与之相关的事件处理接口也不同。
- Java的所有事件类都定义在
java.awt.event
包中,该包中还定义了11个监听者接口,每个接口内部包含了若干处理相关事件的抽象方法,如下表所示:
描述信息 | 接口名称 | 方法(事件) |
---|---|---|
单击按钮,菜单项,文本库及按回车等动作 | ActionListener | actionPerformed(ActionEvent) |
选择了可选项的项目 | ItemListener | itemStateChanged(ItemEvent) |
文本部件内容改变 | TextListener | textValueChanged(TextEvent) |
移动了滚动条等部件 | AdjustmentListener | adjustmentValueChanged(AdjustmentEvent) |
鼠标移动 | MouseMotionListener | mouseDragged(MouseEvent) mouseMoved(MouseEvent) |
鼠标单击等 | MouseListener | mousePressed(MouseEvent) mouseReleased(MouseEvent) mouseEntered(MouseEvent) mouseExited(MouseEvent) mouseExited(MouseEvent) mouseClicked(MouseEvent) |
键盘输入 | KeyListener | keyPressed(KeyEvent) keyReleased(KeyEvent) keyTyped(KeyEvent) |
部件收到或失去焦点 | FocusListener | focusGained(FocusEvent) focusLost(FocusEvent) |
部件移动,缩放,显示/隐藏 | ComponentListener | componentMoved(ComponentEvent) componentHidden(ComponentEvent) componentResized(ComponentEvent) componentShown(ComponentEvent) |
窗口事件 | WindowListener | windowClosing(WindowEvent) windowOpened(WindowEvent) windowIconified(WindowEvent) windowDeiconified(WindowEvent) windowClosed(WindowEvent) windowActivated(WindowEvent) windowDeactivated(WindowEvent) |
容器增加/删除部件 | ContainerListener | componentAdded(ContainerEvent) componentRemoved(ContainerEvent) |
在事件处理代码中区分事件源
- 一个事件源可以注册多个监听者,一个监听者也可以监视多个事件源,在事件处理代码中如何区分事件源呢?不同类型的事件提供了不同类型的方法来区分事件源对象,例如,
ActionEvent
类中提供了如下两个方法:getSourse()
方法:用来获取事件源的对象引用,该方法从父类EventObject
继承而来,其余各类事件对象也可用getSourse()
方法得到事件源的对象引用。getActionCommand()
方法:用来获取按钮事件对象的命令名,按钮对象的命令名默认就是按钮的标签名称,当两个也可以设置不同名称。
- 按钮对象提供了如下方法分别用来设置和获取按钮的标签与命令名:
void setLabel(String label)
:设置按钮的标签。String getLabel()
:返回按钮的标签内容。void setActionCommand(String command)
:设置按钮的命令名。String getActionCommand()
:返回按钮的命令名。
使用事件适配器类
- 从上表可以看出,不少事件的监听者接口中定义了多个方法,而程序员往往只关心其中的一两个方法。
- 为符合接口的实现要求,必须将其他方法写出来并为其提供空的方法体。
- 为此,Java中为那些具有多个方法的监听者接口提供了事件适配器类,这个类通常命名为
XxxAdapter
,在该类中以空方法体实现了相应接口的所有方法。 - 例如,窗体的监听者接口中有7个方法,每个方法对应有
WindowEvent
类中的一个具体事件,他们是WINDOW_ACTIVATED
,WINDOW_DEACTICATED
,WINDOW_OPENED
,WINDOW_CLOSED
,WINDOW_CLOSING
,WINDOW_ICONIFIED
,WINDOW_DEICONIFIED
,类似于动作事件中的getSourse()
方法,在WindowEnent
类中也有如下方法用于获取引发WindowEvent
事件的具体窗口对象。
1 |
|
- 以下结合窗体关闭为例介绍窗体事件适配器类的使用。
[例11-2]:处理窗体的关闭。
- 关闭窗体通常可考虑如下几种操作方式:
- 在窗体中安排一个"关闭”按钮,单击按钮关闭窗体。
- 响应
WINDOW_CLOSING
事件,单击窗体的"关闭”图标将引发该事件。 - 使用菜单命令实现关闭,相应菜单的动作事件。
- 无论哪种均要调用窗体对象的
dispose()
方法来实现窗体的关闭。
1 |
|
-
本程序对监听者的编程用到了两种方式,处理"关闭”按钮事件的监听者是通过实现接口的方式,而处理窗体的"关闭”事件的监听者则采用继承
WindowAdapter
的方式。 -
在
closeWin
类的windowClosing()
方法中,,也可以采用getSource()
方法得到事件源对象,但必须用如下形式的强制转换将其转换为Frame或Window对象:1
Frame frm = (Frame)(e.getSourse());
-
closeWin
类没有设计为内嵌类,如果将其改为MyFrame的内嵌类,则可省略获取窗体对象的代码,就可直接写dispose()
方法。
鼠标事件
- 鼠标事件共有7种情形,用
MouseEvent
类的静态整形常量表示,分别是MOUSE_DRAGGED
,MOUSE_ENTERED
,MOUSE_EXITED
,MOUSE_MOVED
,MOUSE_PRESSED
,MOUSE_RELEASED
,MOUSE_CLICKED
- 鼠标事件的处理通过
MouseListener
和MouseMotionListener
两个接口来描述。MouseListener
负责接收和处理鼠标的Press(按下),release(释放),click(单击),enter(移入)和exit(移出)动作触发的事件。MouseMotionListener
负责接收和处理鼠标的move(移动)和drag(拖动)动作触发的事件,具体应用中对哪种鼠标事件关心,就在相应的事件处理方法中编写代码。
- 以下为
MouseEvent
类的主要方法:public int getX()
:返回发生鼠标事件的X坐标。public int getY()
:返回发生鼠标事件的Y坐标。public Point getPoint()
:返回Point对象,也即鼠标事件发生的坐标点。public int getClickCount()
:返回鼠标单击事件的连击次数。
高级语义事件和低级语义事件
- 在图形界面上进行各类鼠标操作均会导致鼠标事件,它具有更广泛发生性,我们将这类事件称为低级语义事件,例如,在按钮上单击,移动,拖动鼠标均会导致鼠标事件。
- 按钮上的动作事件,则局限于在按钮上单击鼠标才会发生,成为高级语义事件,程序中要关注处理相应事件,必须注册监听者,如果程序对同一操作引发的两类事件均关注,则低级语义事件将先于高级语义事件进行处理。
- 常见的低级语义事件如下:
- 组件事件(ComponentEvent):组件尺寸的变化,移动。
- 容器事件(ContainerEvent):容器中组件的增加,删除。
- 窗口事件(WindowEvent):关闭窗口,图标化。
- 焦点事件(FocusEvent):焦点的获得和丢失。
- 键盘事件(KeyEvent):键按下,释放。
- 鼠标事件(MouseEvent):鼠标单击,移动等。
- 高级事件依赖于触发相应事件的图形部件,如在文本框中按回车键会触发
ActionEvent
事件,单击按钮会触发ActionEcent
事件,活动滚动条会触发AdjustmentEvent
事件,选中项目列表中的某一项就会触发ItemEvent
事件等。
[例11-8]:围棋对弈界面设计。
- 在窗体中要同时安排棋盘和下棋过程中的若干操作按钮,棋盘用一个Canvas部件绘制,下棋过程控制按钮则部署在一个面板上,棋盘上的棋子信息通过一个二维数组记录,数组元素为1表示黑棋,2表示白棋,0表示无棋子。
- 为了方便下棋定位操作,在棋盘上绘制一个红色小方框代表位置的小游标,鼠标移动时小游标也跟随移动,小游标移动时要擦除先前的绘制,所以,小游标采用异或方式绘制,擦除只要将其按相同颜色重绘一次既可。
- 我们可以利用鼠标移动事件处理小游标的移动处理,利用鼠标单击事件处理新下棋子的绘制处理,另外,棋盘及棋子信息利用
paint()
方法实现绘制。 - 程序中引入cx和cy两个变量代表游标位置,引入变量player表示当前轮到黑白谁下子,为了实现棋盘位置和大小调整方便,引入实例变量sx,sy记录棋盘左上角的位置信息,并引入实例变量w代表棋盘格子宽度,绘制的棋子宽度比个字宽度略小。
1 |
|
- 通过
getGraphics()
方法获取画笔进行图形绘制,而不是调用repaint()
方法实现绘制,其好处是避免画面闪烁。
键盘事件
-
键盘事件包含3个,分别对应
KeyEvent
类的几个同名的静态整形常量KEY_PRESSED
,KEY_RELEASED
,KEY_TYPED
-
相应的,与
KeyEvent
事件相对应的监听者接口是KeyListener
,其中包括3个键盘事件对应的抽象方法:-
public void keyPressed(KeyEvent e)
:某个键按下时执行。 -
public void keyReleased(KeyEvent e)
:某个键被释放时执行。public void keyTyped(KeyEvent e)
:KeyTyped
包含KeyPressed
和KeyRelased
两个动作,按键被敲击。
-
[例11-9]:实现可变色小方框的移动及变色,通过键盘的方向键也可控制小方框的移动,通过字母键B,G等可更改小方框的颜色。
1 |
|
- 注意:可以将本程序的
keyTyped
代码放到keyPressed()
方法中,程序运行结果一样,但不能将keyPressed
代码放到keyTyped()
中,这是因为各种控制键按下时,不产生ketTyped
事件,所以,对控制键的编程用keyPressed()
或keyReleased()
方法,而字符键按下时则3个方法均会执行,可选择一个方法进行处理。
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!