一.AWT简介
窗口工具包AWT (Abstract Window Toolkit) 是 API为Java 程序提供的建立图形用户界面GUI (Graphics User Interface)工具集,AWT可用于Java的applet和applications中。它支持图形用户界面编程的功能包括: 用户界面组件;事件处理模型;图形和图像工具,包括形状、颜色和字体类;布局管理器,可以进行灵活的窗口布局而与特定窗口的尺寸和屏幕分辨率无关;数据传送类,可以通过本地平台的剪贴板来进行剪切和粘贴。
1.1: java.awt 包
java.awt包中提供了GUI设计所使用的类和借口,下图中列出了主要类之间的关系.
java.awt设计主要包括三个概念:
组件Component
容器Container
布局管理器LayoutManager
1.2 :java.awt.Component
Component类封装了组件通用的方法和属性,如图形组件对象,大小,显示位置,BlackColor/ForeColor,边界,可见性等.因此许多组件类也就继承了Component类的成员方法和成员变量,相应的成员方法包括:
getComponentAt(int x, int y)
getFont()
getForeground()
getName()
getSize()
paint(Graphics g)
repaint()
update()
setVisible(boolean b)
setSize(Dimension d)
setName(String name)等
1.3:Container
容器(Container)也是一个类,实际上是Component的子类,因此容器本身也是一个组件,具有组件的所有性质,但是它的主要功能是容纳其它组件和容器.
1.4: LayoutManager
每个容器都有一个布局管理器,当容器需要对某个组件进行定位或判断其大小尺寸时,就会调用其对应的布局管理器。
为了使我们生成的图形用户界面具有良好的平台无关性,Java语言中,提供了布局管理器这个工具来管理组件在容器中的布局,而不使用直接设置组件位置和大小的方式。
在程序中安排组件的位置和大小时,应该注意以下两点:
1.容器中的布局管理器负责各个组件的大小和位置,因此用户无法在这种情况下设置组件的这 些属性。如果试图使用Java 语言提供的setLocation(),setSize(),setBounds() 等方法,则都会被布局管理器覆盖。
2.如果用户确实需要亲自设置组件大小或位置,则应取消该容器的布局管理器,方法为:
setLayout(null);
二.Constainer
容器java.awt.Container是Component的子类,一个容器可以容纳多个组件,并使它们成为一个整体。容器可以简化图形化界面的设计,以整体结构来布置界面。所有的容器都可以通过add()方法向容器中添加组件。
有三种类型的容器:Window、Panel、ScrollPane,常用的有Panel, Frame, Applet。
2.1 Frame
Frame的外观就像我们平常在windows系统下见到的窗口,有标题、边框、菜单、大小等等。每个Frame的对象实例化以后,都是没有大小和不可见的,因此必须调用setSize( )来设置大小,调用setVisible(true)来设置该窗口为可见的。
AWT在实际的运行过程中是调用所在平台的图形系统,因此同样一段AWT程序在不同的操作系统平台下运行所看到的图形系统是不一样的。例如在windows下运行,则显示的窗口是windows风格的窗口;而在UNIX下运行时,则显示的是UNIX风格的窗口。
例1
import java.awt.*;
public class MyFrame extends Frame{
public static void main(String args[ ]){
MyFrame fr = new MyFrame("Hello Out There!");
//构造方法
fr.setSize(200,200);
//设置Frame的大小,缺省为(0,0)
fr.setBackground(Color.red);
//设置Frame的背景,缺省为红色
fr.setVisible(true);
//设置Frame为可见,缺省为不可见
}
public MyFrame (String str){
super(str); //调用父类的构造方法
}
}
2.2 : Panel
例2
import java.awt.*;
public class PanelTest1 extends Frame{
public PanelTest1(String str){
super(str);
}
public static void main(String args[]){
PanelTest1 fr=new PanelTest1("Panel Test");
Panel pan=new Panel();
fr.setSize(200,200);
fr.setBackground(Color.red);
fr.setLayout(null);
pan.setSize(100,100);
pan.setBackground(Color.yellow);
fr.add(pan);
fr.setVisible(true);
}
}
三.LayoutManager
java为了实现跨平台的特性并且获得动态的布局效果,java将容器内的所有组件安排给一个"布局管理器"负责管理,如:排列顺序,组件的大小、位置,当窗口移动或调整大小后组件如何变化等功能授权给对应的容器布局管理器来管理,不同的布局管理器使用不同算法和策略,容器可以通过选择不同的布局管理器来决定布局。
布局管理器主要包括:FlowLayout,BorderLayout,GridLayout,CardLayout,GridBagLayout
3.1 FlowLayout
FlowLayout 是Panel,Applet的缺省布局管理器。其组件的放置规律是从上到下、从左到右进行放置,如果容器足够宽,第一个组件先添加到容器中第一行的最左边,后续的组件依次添加到上一个组件的右边,如果当前行已放置不下该组件,则放置到下一行的最左边。
构造方法主要下面几种:
FlowLayout(FlowLayout.RIGHT,20,40);
/*第一个参数表示组件的对齐方式,指组件在这一行中的位置是居中对齐、居右对齐还是居左对齐,第 二个参数是组件之间的横向间隔,第三个参数是组件之间的纵向间隔,单位是象素。*/
FlowLayout(FlowLayout.LEFT);
//居左对齐,横向间隔和纵向间隔都是缺省值5个象素
FlowLayout();
//缺省的对齐方式居中对齐,横向间隔和纵向间隔都是缺省值5个象素
组件初始化大小一般依据组件的正文大小而定;
import java.awt.*;
public class ExGui{
public static void main(String args[])
{
Frame f = new Frame();
f.setLayout(new FlowLayout());
Button button1 = new Button("Okdfdsfasd");
Button button2 = new Button("Open");
Button button3 = new Button("Close");
f.add(button1);
f.add(button2);
f.add(button3);
f.setSize(300,100);
f.setVisible(true);
}
}
3.2:BorderLayout
BorderLayout 是Window,Frame和Dialog的缺省布局管理器。BorderLayout布局管理器把容器分成5个区域:North,South,East,West和Center,每个区域只能放置一个组件。各个区域的位置及大小如下图所示:
在使用BorderLayout的时候,如果容器的大小发生变化,其变化规律为:组件的相对位置不变,大小发生变化。例如容器变高了,则North、South区域不变,West、Center、East区域变高;如果容器变宽了,West、East区域不变,North、Center、South区域变宽。不一定所有的区域都有组件,如果四周的区域(West、East、North、South区域)没有组件,则由Center区域去补充,但是如果Center区域没有组件,则保持空白.
3.3: GridLayout
使容器中各个组件呈网格状布局,平均占据容器的空间。
public class ExGui{
public static void main(String args[])
{
Frame f = new Frame();
//f.setLayout(new FlowLayout());
//f.setLayout(new BorderLayout());
f.setLayout(new GridLayout(3,2));
Button button1 = new Button("Okdfdsfasd");
Button button2 = new Button("Open");
Button button3 = new Button("Close");
f.add(button1);
f.add(button2);
f.add(button3);
f.add(new Button("button4"));
/*
f.add("North",button1);
f.add("South",button2);
*/
f.setSize(300,100);
f.setVisible(true);
}
}
3.4 :CardLayout
CardLayout布局管理器能够帮助用户处理两个以至更多的成员共享同一显示空间,它把容器分成许多层,每层的显示空间占据整个容器的大小,但是每层只允许放置一个组件,当然每层都可以利用Panel来实现复杂的用户界面。
四.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所示
使用授权处理模型进行事件处理的一般方法归纳如下:
1.对于某种类型的事件XXXEvent, 要想接收并处理这类事件,必须定义相应的事件监听器类,该类需要实现与该事件相对应的接口XXXListener;
2.事件源实例化以后,必须进行授权,注册该类事件的监听器,使用addXXXListener(XXXListener ) 方法来注册监听器。
例: TestButton.java
import java.awt.*;
import java.awt.event.*;
public class TestButton{
public static void main(String []args)
{
Frame f=new Frame("Button 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 occured");
}
//本接口只有一个方法,因此事件发生时,系统会自动调用本方法,需要做的操作就把代码写在则个方法里。
}
每类事件都有对应的事件监听器,监听器是接口,根据动作来定义方法。
4.1:KeyEvent
java.lang.Object
java.util.EventObject
java.awt.AWTEvent
java.awt.event.ComponentEvent
java.awt.event.InputEvent
java.awt.event.KeyEvent
与键盘事件KeyEvent相对应的接口是:
public interface KeyListener extends EventListener {
public void keyPressed(KeyEvent ev);
public void keyReleased(KeyEvent ev);
public void keyTyped(KeyEvent ev);
}
当键盘刚按下去时,将调用keyPressed( )方法执行,当键盘抬起来时,将调用keyReleased( )方法执行,当键盘敲击一次时,将调用keyTyped( )方法执行。
4.2 WindowEvent
窗口事件接口:
public interface WindowListener extends EventListener{
public void windowClosing(WindowEvent e);
//把退出窗口的语句写在本方法中
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);
//窗口非激活时调用
}
4.3:AWT事件及其相应的监听器接口
下表列出所有AWT事件及其相应的监听器接口,一共10类事件,11个接口。
事件类别
|
描述信息
|
接口名
|
方法
|
ActionEvent | 激活组件 | ActionListener | actionPerformed(ActionEvent) |
ItemEvent | 选择了某些项目 | ItemListener | itemStateChanged(ItemEvent) |
MouseEvent | 鼠标移动 | MouseMotionListener | mouseDragged(MouseEvent) mouseMoved(MouseEvent) |
鼠标点击等 | MouseListener | mousePressed(MouseEvent) mouseReleased(MouseEvent) mouseEntered(MouseEvent) mouseExited(MouseEvent) mouseClicked(MouseEvent) | |
KeyEvent | 键盘输入 | KeyListener | keyPressed(KeyEvent) keyReleased(KeyEvent) keyTyped(KeyEvent) |
FocusEvent | 组件收到或失去焦点 | FocusListener | focusGained(FocusEvent) focusLost(FocusEvent) |
AdjustmentEvent | 移动了滚动条等组件 | AdjustmentListener | adjustmentValueChanged(AdjustmentEvent) |
ComponentEvent | 对象移动缩放显示隐藏等 | ComponentListener | componentMoved(ComponentEvent) componentHidden(ComponentEvent) componentResized(ComponentEvent) componentShown(ComponentEvent) |
WindowEvent | 窗口收到窗口级事件 | WindowListener | windowClosing(WindowEvent) windowOpened(WindowEvent) windowIconified(WindowEvent) windowDeiconified(WindowEvent) windowClosed(WindowEvent) windowActivated(WindowEvent) windowDeactivated(WindowEvent) |
ContainerEvent | 容器中增加删除了组件 | ContainerListener | componentAdded(ContainerEvent) componentRemoved(ContainerEvent) |
TextEvent | 文本字段或文本区发生改变 | TextListener | textValueChanged(TextEvent) |
1.可以声明多个接口,接口之间用逗号隔开。
……implements MouseMotionListener, MouseListener, WindowListener;
2.可以由同一个对象监听一个事件源上发生的多种事件:
f.addMouseMotionListener(this);
f.addMouseListener(this);
f.addWindowListener(this);
则对象f 上发生的多个事件都将被同一个监听器接收和处理。
3.事件处理者和事件源处在同一个类中。
import java.awt.*;
import java.awt.event.*;
public class TreeEvent implements MouseMotionListener,MouseListener,WindowListener,TextListener{
private Frame f;
private TextField tf;
public static void main(String []args)
{
TreeEvent two=new TreeEvent();
two.go();
}
public void go()
{
f=new Frame("Listeners example");
f.add(new Label("Click and drag the mouse"),"North");
tf=new TextField(30);
tf.addTextListener(this);
f.add(tf,"South");
f.addMouseListener(this);
f.addMouseMotionListener(this);
f.addWindowListener(this);
f.setSize(300,200);
f.setVisible(true);
}
public void textValueChanged(TextEvent e)
{
System.out.println("The text changed");
}
public void mouseDragged(MouseEvent e){
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)
{
System.exit(1);
}
public void windowOpened(WindowEvent e)
{
tf.setText("The Mouse Test");
}
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){}
}