|
例5.7 import java.awt.*; import java.awt.event.*; //事件处理机制,下一节的内容 public class ThreePages implements MousListener { CardLayout layout=new CardLayout(); //实例化一个牌布局管理器对象 Frame f=new Frame("CardLayout"); Button page1Button; Label page2Label; //Label是标签,实际上是一行字符串 TextArea page3Text; //多行多列的文本区域 Button page3Top; Button page3Bottom;
public static void main(String args[]) { new ThreePages().go(); }
Public void go() { f.setLayout(layout); //设置为牌布局管理器layout f.add(page1Button=new Button("Button page"),"page1Button"); /*第二个参数"page1Button"表示的是你对这层牌所取的名字*/ page1Button.addMouseListener(this); //注册监听器 f.add(page2Label=new Label("Label page"),"page2Label"); page2Label.addMouseLisener(this); //注册监听器 Panel panel=new Panel(); panel.setLayout(new BorderLayout()); panel.add(page3Text=new TextArea("Composite page"),"Center"); page3Text.addMouseListener(this); panel.add(page3Top=new Button("Top button") , "North"); page3Top.addMouseListener(this); panel.add(page3Bottom=new Button("Bottom button") ,"South"); page3Bottom.addMouseListener(this); f.add(panel,"panel"); f.setSize(200,200); f.setVisible(true); } …… }
5.容器的嵌套
在复杂的图形用户界面设计中,为了使布局更加易于管理,具有简洁的整体风格,一个包含了多个组件的容器本身也可以作为一个组件加到另一个容器中去,容器中再添加容器,这样就形成了容器的嵌套。下面是一个容器嵌套的例子。
例5.8 import java.awt.*; public class ExGui3{ private Frame f; private Panel p; private Button bw,bc; private Button bfile,bhelp; public static void main(String args[]) { ExGui3 gui = new ExGui3(); gui.go(); }
public void go(){ f = new Frame("GUI example 3"); bw=new Button("West"); bc=new Button("Work space region"); f.add(bw,"West"); f.add(bc,"Center"); p = new Panel(); f.add(p,"North"); bfile= new Button("File"); bhelp= new Button("Help"); p.add(bfile); p.add(bhelp); f.pack(); f.setVisible(true); } }
小 结:
1.Frame是一个顶级窗口。Frame的缺省布局管理器为BorderLayout。
2.Panel 无法单独显示,必须添加到某个容器中。 Panel 的缺省布局管理器为FlowLayout。
3.当把Panel 作为一个组件添加到某个容器中后,该Panel 仍然可以有自己的布局管理器。因此,可以利用Panel 使得BorderLayout 中某个区域显示多个组件,达到设计复杂用户界面的目的 。
4.如果采用无布局管理器 setLayout(null),则必须使用setLocation(),setSize(),setBounds()等方法手工设置组件的大小和位置,此方法会导致平台相关,不鼓励使用。
5.2 AWT事件处理模型
上一节中的主要内容是如何放置各种组件,使图形界面更加丰富多彩,但是还不能响应用户的任何操作,要能够让图形界面接收用户的操作,就必须给各个组件加上事件处理机制。在事件处理的过程中,主要涉及三类对象:
◇ Event-事件,用户对界面操作在java语言上的描述,以类的形式出现,例如键盘操作对应的事件类是KeyEvent。
◇ Event Source-事件源,事件发生的场所,通常就是各个组件,例如按钮Button。
◇ Event handler-事件处理者,接收事件对象并对其进行处理的对象
例如,如果用户用鼠标单击了按钮对象button,则该按钮button就是事件源,而java运行时系统会生成ActionEvent类的对象actionE,该对象中描述了该单击事件发生时的一些信息,然后,事件处理者对象将接收由java运行时系统传递过来的事件对象actionE并进行相应的处理。
由于同一个事件源上可能发生多种事件,因此java采取了授权处理机制(Delegation Model),事件源可以把在其自身所有可能发生的事件分别授权给不同的事件处理者来处理。比如在Canvas对象上既可能发生鼠标事件,也可能发生键盘事件,该Canvas对象就可以授权给事件处理者一来处理鼠标事件,同时授权给事件处理者二来处理键盘事件。有时也将事件处理者称为监听器,主要原因也在于监听器时刻监听着事件源上所有发生的事件类型,一旦该事件类型与自己所负责处理的事件类型一致,就马上进行处理。授权模型把事件的处理委托给外部的处理实体进行处理,实现了将事件源和监听器分开的机制。事件处理者(监听器)通常是一个类,该类如果要能够处理某种类型的事件,就必须实现与该事件类型相对的接口。例如例5.9中类ButtonHandler之所以能够处理ActionEvent事件,原因在于它实现了与ActionEvent事件对应的接口ActionListener。每个事件类都有一个与之相对应的接口。
将事件源对象和事件处理器(事件监听器)分开。如图5.2所示 打个不太恰当的比喻,比如说有一位李先生,李先生可能会发生很多法律纠纷,可能是民事法律纠纷,也可能是刑事法律纠纷,那么李先生可以请律师,他可以授权王律师负责帮他打民事法律的官司,同时也可以授权张律师帮他打刑事法律的官司。这个请律师的过程从李先生的角度来看,就是授权的过程,而从王律师和张律师的角度来看,一旦被授权,他们就得时刻对李先生负责,"监听"着李先生,一旦发生民事纠纷了,王律师就要马上去处理,而一旦发生刑事纠纷了,张律师就要马上进行处理。此时此刻,李先生就是事件源,王律师是一个事件处理者,张律师是另外一个事件处理者,民事纠纷和刑事纠纷就是不同类型的事件。
例5.9 import java.awt.*; import java.awt.event.*; public class TestButton { public static void main(String args[]) { Frame f = new Frame("Test"); Button b = new Button("Press Me!"); b.addActionListener(new ButtonHandler()); /*注册监听器进行授权,该方法的参数是事件处理者对象,要处理的事件类型可以从方法名中看出,例如本方法要授权处理的是ActionEvent,因为方法名是addActionListener。*/ f.setLayout(new FlowLayout()); //设置布局管理器 f.add(b); f.setSize(200,100); f.setVisible(true); } } class ButtonHandler implements ActionListener { //实现接口ActionListener才能做事件ActionEvent的处理者 public void actionPerformed(ActionEvent e) //系统产生的ActionEvent事件对象被当作参数传递给该方法 { System.out.println("Action occurred"); //本接口只有一个方法,因此事件发生时,系统会自动调用本方法,需要做的操作就把代码写在则个方法里。 } }
使用授权处理模型进行事件处理的一般方法归纳如下:
1.对于某种类型的事件XXXEvent, 要想接收并处理这类事件,必须定义相应的事件监听器类,该类需要实现与该事件相对应的接口XXXListener;
2.事件源实例化以后,必须进行授权,注册该类事件的监听器,使用addXXXListener(XXXListener ) 方法来注册监听器。
|