Java AWT入门教程实例源码学习4。
处理发生在某个GUI组件上的XxxEvent事件的某种情况,其事件处理的通用编写流程如下:
(1)编写一个实现了XxxListener接口的事件监听器类;
(2)在XxxListener类中用于处理该事件情况的方法中,编写处理代码;
(3)调用组件的addXxxListener方法,将类XxxListener创建的实例对象注册到GUI组件上。
我们通过一个实例说明事件处理模型的应用。
imp
imp
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)。
imp
imp
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)。当一个内部类的类声声只是在创建此类对象时用了一次,而且要产生的新类需继承于一个已有的父类或实现一个接口时,才能考虑用匿名类,由于匿名类本身无名,因此它也就不存在构造方法,它需要显式地调用一个无参的父类的构造方法,并且重写父类的方法。所谓的匿名,就是该类连名字都没有,只是显式地调用一个无参的父类的构造方法。
下面是一个实例。
imp
imp
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类,重写所需要的方法,无关的方法则不用实现。事件适配器为我们提供了一种简单的实现监听器的手段,可以缩短程序代码。