Java AWT入门教程实例源码学习4



Java AWT入门教程实例源码学习4。

处理发生在某个GUI组件上的XxxEvent事件的某种情况,其事件处理的通用编写流程如下:

(1)编写一个实现了XxxListener接口的事件监听器类;

(2)在XxxListener类中用于处理该事件情况的方法中,编写处理代码;

(3)调用组件的addXxxListener方法,将类XxxListener创建的实例对象注册到GUI组件上。

我们通过一个实例说明事件处理模型的应用。

import java.awt.*;

import java.awt.event.*;

public class ThreeListener implements MouseMotionListener, MouseListener,

WindowListener {

//实现了3个接口

private Frame f;

private TextField tf;

public static void main(String args[])

{

ThreeListener two = new ThreeListener();

two.go(); }

public void go() {

f = new Frame(“Three listeners example”);

f.add(new Label(“Click and drag the mouse”),”North”);

tf = new TextField(30);

f.add(tf,”South”); //使用默认的布局管理器

f.addMouseMotionListener(this); //注册监听器MouseMotionListener

f.addMouseListener(this); //注册监听器MouseListener

f.addWindowListener(this); //注册监听器WindowListener

f.setSize(300,200);

f.setVisible(true);

}

public void mouseDragged (MouseEvent e) {

//实现mouseDragged方法

String s = “Mouse dragging : X=”+e.getX()+”Y = “+e.getY();

tf.setText(s);

}

public void mouseMoved(MouseEvent e){}

//对其不感兴趣的方法可以不实现,方法体为空

public void mouseClicked(MouseEvent e){}

public void mouseEntered(MouseEvent e){

String s = “The mouse entered”;

tf.setText(s);

}

public void mouseExited(MouseEvent e){

String s = “The mouse has left the building”;

tf.setText(s);

}

public void mousePressed(MouseEvent e){}

public void mouseReleased(MouseEvent e){ }

public void windowClosing(WindowEvent e) {

//为了使窗口能正常关闭,程序正常退出,需要实现windowClosing方法

System.exit(1);

}

public void windowOpened(WindowEvent e) {}

//对其不感兴趣的方法可以不实现,方法体为空

public void windowIconified(WindowEvent e) {}

public void windowDeiconified(WindowEvent e) {}

public void windowClosed(WindowEvent e) {}

public void windowActivated(WindowEvent e) { }

public void windowDeactivated(WindowEvent e) {}

}

上例具有如下几个特点。

(1)可以声明多个接口,接口之间用逗号隔开。

…implements MouseMotionListener, MouseListener, WindowListener;

(2)可以由同一个对象监听一个事件源上发生的多种事件:

f.addMouseMotionListener(this);

f.addMouseListener(this);

f.addWindowListener(this);

则对象f上发生的多个事件都将被同一个监听器接收和处理。

(3)事件处理者和事件源处在同一个类中。本例中事件源是Frame f,事件处理者是类ThreeListener,其中事件源Frame f是类ThreeListener的成员变量。

(4)可以通过事件对象获得详细资料,比如,本例中就通过事件对象获得了鼠标发生时的坐标值。

public void mouseDragged(MouseEvent e) {

String s=”Mouse dragging :X=”+e.getX()+”Y=”+e.getY();


tf.setText(s);

}

2.用内部类实现事件处理

我们在前面讲解了内部类的概念,其实内部类的一个主要应用就在于图形用户界面开发中的事件处理。

内部类(Inner Class)是被定义于另一个类中的类,使用内部类的主要原因是由于:

— 一个内部类的对象可访问外部类的成员方法和变量,包括私有的成员;

— 实现事件监听器时,采用内部类、匿名类编程非常容易实现其功能;

— 编写事件驱动程序,内部类很方便。

因此,内部类所能够应用的地方往往是在AWT的事件处理机制中。

我们看一个实例。这里我们使用第2种内部类,即成员内部类(Memebr Inner Class)。

import java.awt.* ;

import java.awt.event.*;

public class InnerClass{

private Frame f;

private TextField tf;

public InnerClass(){

f=new Frame(“Inner classes example”);

tf=new TextField(30);

}

public voidi launchFrame(){

Label label=new Label(“Click and drag the mouse”);

f.add(label,BorderLayout.NORTH);

f.add(tf,BorderLayout.SOUTH);

f.addMouseMotionListener(new MyMouseMotionListener());//参数为内部类对象

f.setSize(300,200);

f.setVisible(true);

}

class MyMouseMotionListener extends MouseMotionAdapter{ //内部类开始

public void mouseDragged(MouseEvent e) {

String s=”Mouse dragging: x=”+e.getX()+”Y=”+e.getY();

tf.setText(s); }

} ;

public static void main(String args[]) {

InnerClass obj=new InnerClass();

obj.launchFrame();

}

}//内部类结束

}

我们也可以使用第4种内部类,即匿名内部类(Anonymous Inner Class)。当一个内部类的类声声只是在创建此类对象时用了一次,而且要产生的新类需继承于一个已有的父类或实现一个接口时,才能考虑用匿名类,由于匿名类本身无名,因此它也就不存在构造方法,它需要显式地调用一个无参的父类的构造方法,并且重写父类的方法。所谓的匿名,就是该类连名字都没有,只是显式地调用一个无参的父类的构造方法。

下面是一个实例。

import java.awt.* ;

import java.awt.event.*;

public class AnonymousClass{

private Frame f;

private TextField tf;

public AnonymousClass(){

f=new Frame(“Inner classes example”);

tf=new TextField(30);

}

public void launchFrame(){

Label label=new Label(“Click and drag the mouse”);

f.add(label,BorderLayout.NORTH);

f.add(tf,BorderLayout.SOUTH);

f.addMouseMotionListener(new MouseMotionAdapter(){ //匿名类开始

public void mouseDragged(MouseEvent e){

String s=”Mouse dragging: x=”+e.getX()+”Y=”+e.getY();

tf.setText(s); }

} ); //匿名类结束

f.setSize(300,200);

f.setVisible(true);

}

public static void main(String args[]) {

AnonymousClass obj=new AnonymousClass();

obj.launchFrame();

}

}

其实大家仔细分析一下,上面两个实例实现的都是完全一样的功能,只不过采取的方式不同。其中一个实例的事件处理类是一个内部类,而另一个实例的事件处理类是匿名类,可以说,从类的关系来看是越来越不清楚,但是程序却越来越简练。熟悉这两种方式有助于大家编写图形界面的程序。

3.4   适配器(Adapter)

Java语言类的层次非常分明,它只支持单继承。为了实现多重继承的能力,Java用接口来实现,一个类可以实现多个接口,这种机制比多重继承具有更简单、灵活、更强的功能。在AWT中就经常用到声明和实现多个接口。请记住:无论实现了几个接口,接口中已定义的方法必须一一实现,如果对某事件不感兴趣,可以不具体实现其方法,而用空的方法体来代替,但却必须所有方法都要写上。这样一来会有一些不便,为了解决这个问题,AWT使用了适配器(Adapter),Java语言为一些Listener接口提供了适配器类(Adapter)。我们可以通过继承事件所对应的Adapter类,重写所需要的方法,无关的方法则不用实现。事件适配器为我们提供了一种简单的实现监听器的手段,可以缩短程序代码。