图形用户界面的行为
事件类型
我们已经介绍了在单一类型事件上下文中从组件接收事件的通用机制。事件类的层次结构图如下所示。许多事件类在java.awt.event包中,也有一些事件类在API的其他地方。
对于每类事件,都有一个接口,这个接口必须由想接收这个事件的类的对象实现。这个接口还要求定义一个或多个方法。当发生特定的事件时,就会调用这些方法。表9-1列出了这些(事件)类型,并给出了每个类型对应的接口名称,以及所要求定义的方法。这些方法的名称是易于记忆的,名称表示了会引起这个方法被调用的源或条件。
方法类型和接口
Category
Interface Name
Methods
Action
ActionListener
actionPerformed(ActionEvent)
Item
ItemListener
itemStateChanged(ItemEvent)
Mouse
motion
MouseMotionListener
mouseDragged(MouseEvent)
mouseMoved(MouseEvent)
Mouse
button
MouseListener
mousePressed(MouseEvent)
mouseReleased(MouseEvent)
mouseEntered(MouseEvent)
mouseExited(MouseEvent)
mouseClicked(MouseEvent)
Key
KeyListener
keyPressed(KeyEvent)
keyReleased(KeyEvent)
keyTyped(KeyEvent)
Focus
FocusListener
focusGained(FocusEvent)
focusLost(FocusEvent)
Adjustment
AdjustmentListener
adjustmentValueChanged
(AdjustmentEvent)
Component
ComponentListener
componentMoved(ComponentEvent)
componentHidden(ComponentEvent)
componentResized(ComponentEvent)
componentShown(ComponentEvent)
方法类型和接口(续)
复杂的范例
本节将考察一个更复杂的Java软件范例。它将跟踪鼠标被按下时,鼠标的移动情况(鼠标拖动)。这个范例还将监测当鼠标没有按下时,鼠标的移动情况(鼠标移动)。
当鼠标按下或没有按下时,移动鼠标产生的事件会被实现了MouseMotionListener接口的类的对象检取。这个接口要求定义两个方法,mouseDragged()和mouseMoved()。即使你只对鼠标拖动感兴趣,也必须提供这两个方法。然而,mouseMoved()的体可以是空的。
要检取其他鼠标事件,包括鼠标点击,必须定义MouseListener接口。这个接口包括若干个事件,即:mouseEntered,
mouseExited, mousePressed, mouseReleased和 mouseClicked。
发生鼠标或键盘事件时,有关鼠标的位置和所按下的键的信息可以从事件中得到。代码如下:
1.import java.awt.*;
2.import
java.awt.event.*;
3.
4.public class TwoListen
implements
5.MouseMotionListener,
MouseListener {
6.private Frame f;
7.private TextField tf;
8.
9.public static void
main(String args[]) {
10.TwoListen two = new TwoListen();
11.two.go();
12.}
13.
复杂的范例(续)
1.public void go() {
2.f = new Frame("Two
listeners example");
3.f.add (new Label ("Click
and drag the mouse"),
4."BorderLayout.NORTH");
5.tf = new TextField
(30);
6.f.add (tf,
"BorderLayout.SOUTH");
7.
8.f.addMouseMotionListener(this);
9.f.addMouseListener
(this);
10.f.setSize(300, 200);
11.f.setVisible(true);
12.}
13.
14.// These are MouseMotionListener
events
15.public void mouseDragged (MouseEvent e)
{
16.String s =
17."Mouse dragging: X = " + e.getX() +
18." Y = " + e.getY();
19.tf.setText (s);
20.}
21.
22.public void mouseMoved (MouseEvent e)
{
23.}
24.
25.// These are MouseListener events
26.public void mouseClicked (MouseEvent e)
{
27.}
28.
29.public void mouseEntered (MouseEvent e)
{
30.String s = "The mouse entered";
31.tf.setText (s);
32.}
复杂的范例(续)
1.public void mouseExited
(MouseEvent e) {
2.String s = "The mouse has
left the building";
3.tf.setText (s);
4.}
5.
6.public void mousePressed
(MouseEvent e) {
7.}
8.
9.public void mouseReleased
(MouseEvent e) {
10.}
11.}
这个范例中的一些地方值得注意。它们将在以下的几节中讨论。
定义多重接口
这个类由第4行中的如下代码声明:
implements MouseMotionListener, MouseListener
声明多个接口时,可以用逗号隔开。
监听多个源
如果你在第11行和第12行中,调用如下方法:
两种类型的事件都会引起TwoListen类中的方法被调用。一个对象可以“监听”任意数量的事件源;它的类只需要实现所要求的接口。
f.addMouseListener(this);
f.addMouseMotionListener(this);
复杂的范例(续)
获取关于事件的细节
调用处理器方法(如mouseDragged())时所带的事件参数可能会包含关于源事件的重要信息。为了确定可以获取关于某类事件的哪些细节时,你应当查看java.awt.event包中合适的类文档。
多监听者
AWT事件监听框架事实上允许同一个组件带有多个监听者。一般地,如果你想写一个程序,它基于一个事件而执行多个动作,把那些行为编写到处理器的方法里即可。然而,有时一个程序的设计要求同一程序的多个不相关的部分对于同一事件作出反应。这种情况是有可能的,例如,将一个上下文敏感的帮助系统加到一个已存在的程序中。
监听者机制允许你调用addXXXlistener方法任意多次,而且,你可以根据你的设计需要指定任意多个不同的监听者。事件发生时,所有被注册的监听者的处理器都会被调用。
事件Adapters(适配器)
你定义的Listener可以继承Adapter类,而且只需重写你所需要的方法。例如:
实现每个Listener接口的所有方法的工作量是非常大的,尤其是MouseListener接口和ComponentListener接口。
以MouseListener接口为例,它定义了如下方法:
- mouseClicked(MouseEvent)
- mouseEntered(MouseEvent)
- mouseExited(MouseEvent)
- mousePressed(MouseEvent)
- mouseReleased(MouseEvent)
为了方便起见,Java语言提供了Adapters类,用来实现含有多个方法的类。这些Adapters类中的方法是空的。
你可以继承Adapters类,而且只需重写你所需要的方法。例如:
1.import java.awt.*;
2.import
java.awt.event.*;
3.
4.public class
MouseClickHandler extends MouseAdapter {
5.
6.// We just need the
mouseClick handler, so we use
7.// the Adapter to avoid
having to write all the
8.// event handler
methods
9.public void mouseClicked
(MouseEvent e) {
10.// Do something with the mouse
click...
11.}
12.}
匿名类
可以在一个表达式的域中,包含整个类的定义。这种方法定义了一个所谓的匿名类并且立即创建了实例。匿名类通常和AWT事件处理一起使用。例如:
1.import java.awt.*;
2.import
java.awt.event.*;
3.public class AnonTest
{
4.private Frame f;
5.private TextField tf;
6.
7.public static void
main(String args[])
8.{
9.AnonTest obj = new
AnonTest();
10.obj.go();
11.}
12.
匿名类(续)
1.public void go() {
2.f = new Frame("Anonymous
classes example");
3.f.add(new Label("Click
and drag the " +
4."
mouse",BorderLayout.NORTH);
5.tf = new TextField
(30);
6.f.add(tf,BorderLayout.SOUTH);
7.
8.f.addMouseMotionListener
( new
9.MouseMotionAdapter()
{
10.public void mouseDragged (MouseEvent e)
{
11.String s =
12."Mouse dragging: X = " + e.getX() +
13." Y = " + e.getY();
14.tf.setText (s);
15.}
16.} ); //
parenthesis
17.
18.f.addMouseListener (new
MouseClickHandler());
19.f.setSize(300, 200);
20.f.setVisible(true);
21.}
22.}