第 8章 Java的 GUI设计
第 8章 Java的 GUI设计
8.1 AWT基础
8.2 窗口类
8.3 AWT基本组件
8.4 菜单
8.5 布局管理器
8.6 Java AWT事件处理机制
8.7 Swing基础
第 8章 Java的 GUI设计
8.1 AWT 基 础
开发图形界面的应用程序时, 需要用到 AWT(抽象
图形工具集 )。 AWT是 Java开发工具包 (JDK)的一部分,
是 Java基本类 (JFC)的核心 。 AWT的作用是给用户提供
基本的界面组件, 如:窗口, 按键, 菜单等 。 此外,
AWT还提供事件处理结构, 支持剪贴板, 数据传输和
图像操作 。
第 8章 Java的 GUI设计
在 Java 1.0中,AWT最初的设计目标是提供一个用
来建立图形用户界面的独立平台,可以让程序员组建
一个通用的 GUI,使其在所有平台上都能正常显示。
遗憾的是,这个目标并没有很好的实现,但幸运的是,
这种情况从 Java 1.1以后得到了大的改进。从 Java 1.2开
始,AWT添加了被称为,Swing”的新 GUI库。
第 8章 Java的 GUI设计
Swing是基于 AWT基本结构创建的二级用户界面工
具集 。 与旧的 AWT相比, Swing提供更加丰富的组件
集, Swing中所提供的组件集几乎可以替代所有 AWT
中原有的组件 。 由此, 许多人也许会产生 Swing是
AWT的替代物的误解, 而实际上 Swing是基于 AWT之
上创建的 。 因此, 为了准确的掌握 Swing组件集的工作
方式, 必须首先掌握 AWT组件的行为及其工作原理 。
第 8章 Java的 GUI设计
8.1.1 java.awt包简介
AWT在 java.awt包中提供, 表 8.1列出了 AWT中的
Java软件包 。
AWT包含四个主要的类:组件类 (Component),容
器类 (Container),图形类 (Graphics)和布局管理器类
(LayoutManager和 LayoutManager2)。
第 8章 Java的 GUI设计
● Component(组件 )类 —— 菜单, 按键, 列表等组件的抽
象基本类 。
● Container(容器 )类 —— 扩展 Component的抽象基本类 。
由 Container 派 生 的类 有 Panel, Applet, Window,
Dialog和 Frame类等 。 在容器中, 可以包含多个组件 。
● Graphics(图形类 )类 —— 定义组件内图形操作的基本类 。
每个组件都有一个相关的图形对象 。
● LayoutManager(布局管理器 )类 —— 定义容器中组件的
位置和尺寸的接口 。 Java中定义了几种默认的布局管
理器 。
第 8章 Java的 GUI设计
表 8.1 AWT中的软件包
软 件 包 描 述
java.awt 基本组件实用工具
java.awt.accessibility 辅助技术
java.awt.color 颜色和颜色空间
java.awt.datatransfer 支持剪贴板和数据传输
java.awt.dnd 支持拖放
java.awt.event 事件类和监听器
java.awt.font 2D API字体软件包
java.awt.geom,2D API几何软件包
第 8章 Java的 GUI设计
java.awt.im 引入方法
java.awt.image 图像处理工具包
java.awt.peer 同位体组件, 界面包
java.awt.print 支持打印 2D API
java.awt.swing Swing组件
java.awt.test 测试 AWT方法有限子集的独立 applet
第 8章 Java的 GUI设计
组件, 容器和布局管理器构成了 AWT中的简单基
础关系:容器中可以包含组件;所有的容器都包含布
局管理器 (java.awt.Container类除外 ),用来指定容器中
组件的位置和形状 。 图形类则提供在组件中显示文本
和图形的方法 。 AWT中的许多操作都发生在组件, 容
器和布局管理器之间 。
第 8章 Java的 GUI设计
8.1.2 AWT组件类层次
组件是构成 AWT的基础 。 AWT中包括大量的组件,
其中大约有一半的类由 java.awt.Component类扩展而来,
所以, Component和它所支持的类是 AWT的基础 。
java.awt.Component类是一个抽象类, 它为其派生类
提供了许多功能 。 例如, 一个组件可以有以下成员:图
形对象, 位置, 尺寸, 父容器, 前景和背景色, 最小 /最
大和首选尺寸等 。
第 8章 Java的 GUI设计
Java语言中, 面板 (Panel),滚动条 (Scrollbar),按
键 (Button),标签 (Label)等等用户界面组件一般都派生
自 java.awt.Component类 。 图 8.1是一些主要的 AWT组
件的结构层次 。
第 8章 Java的 GUI设计
图 8.1
B u t t o nC o m p o n e n t
T e x t C o m p o n e n t
S c r o l l b a r
L a b e l
C h e c k b o x
C a n v a s
C o n t a i n e r
W i n d o w
P a n e l A p p l e t
F r a m e
D i a l o g
T e x t F i e l d
T e x t A r e a
第 8章 Java的 GUI设计
8.1.3 容器和布局管理器
从 java.awt.Container类扩展的类称为容器,
Container也是一个从 Component扩展的抽象类。顾名思
义,容器就是用来包含组件的,一个容器可以包含多
个组件,也可以使用容器将相关组件关联在一起,成
为一个整体。合理的使用容器可以简化图形界面的设
计,而且对于组件的显示安排也很有用。表 8.2列出了
从 java.awt.Container类派生的 AWT容器类。后面我们
还会详细说明这些容器的使用。
第 8章 Java的 GUI设计
表 8.2 Container的子类
子类 说 明
Applet Panel.Applet的扩展, 使所有 Applet的超类
Dialog 对话框 (可模式化或非模式化 Window的扩展 )
FieldDialog 用于选择文件的对话框
Frame Window的扩展, 应用程序的容器, 可以有菜单和标题栏
Panel Container的扩展, 简单的容器
ScrollPane 滚动组件
Window Container的扩展, 没有菜单或边界, 是 Frame和 Dialog的超类
第 8章 Java的 GUI设计
容器只能记录包含的组件, 而布局管理器则负责
指定容器中组件的位置和大小 。 Java的布局管理器只
需要确定组件和其他组件的相对位置, 而不需要决定
它的坐标, 这样的安排令与平台无关的用户界面更易
于实现 。 AWT中提供了五种布局管理器:
● BorderLayout:该布局管理器将容器划分为东,
南, 西, 北, 中五个区域, 当添加组件到容器中时,
要指明将容器放置到哪一个区域中 。
第 8章 Java的 GUI设计
● CarderLayout:该布局管理器将容器当作一个卡片栈,
添加到容器中的每个组件都被放置在一个单独的卡片
上, 但每次只能显示一张卡片 。
● FlowLayout:该布局管理器将添加到容器中的组件按
从上到下, 从左到右的顺序依次排列 。
● GridLayout:该布局管理器将容器分成相同尺寸的网
格, 将添加到容器中的组件按从左到右, 从上到下的
顺序放置在每一个网格中 。
第 8章 Java的 GUI设计
● GridBagLayout:该布局管理器也是将容器分成网
格,它和 GridLayout不一样的是,一个组件可以占据不
止一个网格的位置。
关于布局管理器将在后面的章节中进行更深入的
讨论,现在最重要的是站在高层次上理解布局管理器
是如何协助容器管理组件的布局的。
第 8章 Java的 GUI设计
8.1.4 可视组件的始祖类 ——Component类
前面已经提到, Component类是大多数组件的超
类, 而 Component类则直接继承 Object类 。 Component
类是一个抽象类, 所以是不能直接使用, 它为子类提
供了非常 多的虚 拟方 法 。 我 们先简 单介绍 一下
Component类提供的一些主要方法:
● public boolean contains(int x,int y)
● public boolean contains(Point p)
以上两个方法用于检查 (x,y)或者对象 p这个点是
否落在组件的范围之内 (其中, (x,y)坐标是相对于此组
件的左上角的 ),是则返回 true,否则返回 false。
第 8章 Java的 GUI设计
● public Color getBackground()
返回组件的背景颜色, 若组件没有设置背景颜色,
则会返回其父组件 (包含该组件的组件 )的背景颜色 。
● public void setBackground(Color c)
设置组件的背景颜色, 若参数 c的值为 null,则会
将背景颜色设为其父组件的背景颜色 。
● public Rectangle getBounds()
返回组件外框矩形的范围, 这个范围定义了组件
的宽, 高和相对其容器的坐标位置 。
第 8章 Java的 GUI设计
● public void setBounds(int x,int y,int width,int height)
● public void setBounds(Rectangle r)
设置组件的位置, 宽度和高度, 可用于移动组件
或改变其大小 。 除非此组件的容器没有使用布局管理
器, 否则这两个方法不生效 。
● public Component getComponentAt(int x,int y)
● public Component getComponentAt(Point p)
第 8章 Java的 GUI设计
判断组件或组件中的子组件 (包含的组件 )中, 是否
有一个包含 (x,y)这个点的组件, 是则返回该组件, 否
则返回 null。 该方法只检查一级子组件, 如果点 (x,y)在
其子组件的子组件中, 则只会返回该组件第一级的子
组件 。
● public Cursor getCursor()
返回组件的鼠标光标对象 。 如果该组件没有设置
鼠标光标, 则返回其父组件的鼠标光标 。
第 8章 Java的 GUI设计
● public void setCursor(Cursor cursor)
设置组件的鼠标光标, 例如将 Button的光标改为手
指, 将 Panel的光标改为放大镜等, 当鼠标移动到这些
对象上时会产生相应的变化 。 若参数为 null,则设成和
父组件的光标一样 。
● public Font getFont()
返回组件的字体, 若组件没有设置字体, 则返回
其父组件的字体 。
● public void setFont(Font f)
设置组件的字体, 若参数 f的值为 null,则会采用其
父组件的字体 。
第 8章 Java的 GUI设计
● public Color getForeground()
返回组件的前景颜色, 若组件没有设置前景颜色,
则会返回其父组件的前景颜色 。
● public void setForeground(Color c)
设置组件的前景颜色, 若参数 c的值为 null,则会将
前景颜色设为其父组件的前景颜色 。
● public Graphics getGraphics()
所有可视组件都有属于自己的 Graphics对象可供画
图, 此方法返回该组件的 Graphics对象 。 但要注意, 若
此组件还没有显示在屏幕上则会返回 null。
第 8章 Java的 GUI设计
● public Point getLocation()
● public int getX()
● public int getY()
这三个方法用于返回组件矩形外框的左上角的坐
标,这个坐标也是相对于其父组件而言的。 getX()和
getY()的作用与 getLocation().x和 getLocation().y或
getBounds().x和 getBounds().y一样,但推荐使用 getX()
和 getY(),因为这两个方法无需内存分配。
第 8章 Java的 GUI设计
● public void setLocation(int x,int y)
● public void setLocation(Point p)
移动该组件到左上角的由 (x,y)或点对象 p所指定的
新位置, 坐标也是相对于其父组件的 。 须注意的是, 如
果此组件使用了 layout manager,这两个方法将不生效 。
● public Container getParent()
返回该组件的父组件, 若没有父组件将返回 null。
第 8章 Java的 GUI设计
● public Dimension getSize()
● public int getWidth()
● public int getHeight()
返回该组件的高度和宽度 。 与 getX()和 getY()一样,
应该使用 getWidth()和 getHeight()而不是 getSize().width
和 getSize().height 或 getBounds().width 和
getBounds().height。
● public void setSize(int width,int height)
第 8章 Java的 GUI设计
● public void setSize(Dimentsion d)
改变组件的高度与宽度 。 如果该组件使用了 layout
manager,这两个方法将无效 。
● public boolean isEnabled()
检查组件当前状态, 可用状态则返回 true,否则返
回 false。 组件的可用状态指组件可以接收用户输入及
产生事件的状态, 如 Windows中变灰的按键, 就是非
可用状态的 。
● public void setEnabled(boolean b)
更改组件的状态为可用或不可用 。
第 8章 Java的 GUI设计
● public boolean isVisible()
检查当组件的父组件为可见的时候, 此组件是否
为可见, 是则返回 true,否则返回 false。 除了顶层窗口
(如 Frame)外, 组件默认初始为可见 。
● public void setVisible(boolean b)
根据参数 b的值改变窗口状态为可见或隐藏 。
第 8章 Java的 GUI设计
● public void paint(Graphics g)
在屏幕上绘制组件, 当组件第一次显示或者需要
重绘时该方法会自动被调用 。 如果需要改变某个基本
组件的样式, 可以通过重载这个函数来实现 。 重载这
个函数不需要调用 super.paint(g)。
● public void repaint()
将组件重画一遍 。 当一个组件需要重画时, 如从
隐藏变为可见, 或者被其他窗口遮住后那个窗口移开
了, 系统就会自动调用该方法, 该方法又立即调用
update()方法 。
第 8章 Java的 GUI设计
● public void update(Graphics g)
该方法的作用是将组件占据的矩形范围清成背景
色, 然后调用 paint()方法重画这个组件 。 在动画技术中,
经常需要用到一个叫 Double Buffering(双缓冲技术 )的技
巧来避免画面的闪烁, 这就需要重载 update()和 paint()
这两个方法来实现 。 应注意的是, 重载 update()方法的
时候, 应该要调用 super.update()方法或者手动调用
paint()方法 。
● public String toString()
返回该组件的文字描述 。
第 8章 Java的 GUI设计
8.2 窗 口 类
AWT提供了三个在屏幕上显示窗口的组件:
Window,Frame和 Dialog。 这三个组件都用于显示窗口,
而且相互之间的区别也不明显, 因此有时候很难确定
到底使用哪个组件更好 。 为了帮助大家区分它们的不
同用法, 表 8.3列出了各组件的属性特征 。
第 8章 Java的 GUI设计
表 8.3 Window,Frame与 Dialog组件的属性
属 性 Window Frame Dialog
模式化 不是 不是 不是 (可设置 )
可调大小 不可 可 可
标题栏 无 有 有
边界 无 有 有
标题 无 有 有
菜单栏 无 有 无
焦点管理器 有 有 有
警告字符串 有 有 有
图表 无 有 无
定位到框架 可 不可 可
第 8章 Java的 GUI设计
8.2.1 窗口 (Window)
java.awt.Window是三个窗口组件中最基本的组件,
它实际上是 Frame与 Dialog组件的超类 。 窗口组件没有
边界, 标题栏与菜单栏, 而且大小不可以调整 。 其次,
如果用户在程序设计过程中, 需要利用悬浮在其他组
件上方的无边界矩形框显示信息, 则窗口是最佳选择 。
常用窗口实现的界面包括:产品信息的封面 (如 Outlook
等软件启动时, 显示在屏幕中间且几秒后自动消失的
封面窗口 ),提示帮助信息 (如使用金山词霸等软件时,
移动鼠标到某个英文单词上时自动弹出的解释信息 )等 。
第 8章 Java的 GUI设计
下面我们通过一个例子来学习如何使用窗口类:
例 8.1 FrameDemo.java
import java.awt.*;
public class SplashDemo extends Frame
{ Window window;
static public void main(String[] args)
{SplashDemo frame = new SplashDemo(); }
public SplashDemo()
{ window = new Window(this);
第 8章 Java的 GUI设计
Dimension scmSize =
Toolkit.getDefaultToolkit().getScreenSize();
int width = 300;
int height = 200;
window.setLocation(scmSize.width/2-
(width/2),scmSize.height/2-(height/2));
window.setSize(width,height);
window.show();
第 8章 Java的 GUI设计
window.toFront();
try { Thread.currentThread().sleep(3000);}
catch (Exception e) {e.printStackTrace();}
window.dispose();
System.exit(0); }
}
这是个使用 Window的窗口在屏幕上显示一个矩形
窗口类的实例, 这个窗口没有边界, 标题栏与菜单栏,
在屏幕上停留 3秒后自动消失 。 如果在窗口中加载一幅
图片, 则能实现一个类似 Outlook的封面窗口 (在窗口中
加载图片的方法我们将在第 9章中学习 )。
第 8章 Java的 GUI设计
程序中用到了工具类的方法
Toolkit.getDefaultToolkit().getScreenSize()。 Toolkit类是
一个包含许多有用的本地工具方法的类。
getScreenSize()方法的作用是取得显示器的像素尺寸。
程序的运行结果如图 8.2所示。
第 8章 Java的 GUI设计
图 8.2
第 8章 Java的 GUI设计
8.2.2 框架 (Frame)
java.awt.Frame是 Window的一个子类, 它是带有标
题栏和边界的窗口, 而且允许调整大小 。 另外, 用户
还可以为框架附加一个菜单栏 。 用户在程序设计过程
中, 当程序窗口需要图表化或者需要包含菜单栏时,
则可以选择使用框架组件 。
构造一个框架后, 可以用 add()方法来给框架添加
组件 。 框架的缺省布局管理器属性是 BorderLayout。 可
以用 setLayout()方式来改变布局管理器属性 。
第 8章 Java的 GUI设计
框架类中的 Frame(String) 构造方法创建一个由
String规定标题的新的不可见的框架对象 。
例 8.2 FrameDemo.java
import java.awt.*;
public class FrameDemo extends Frame
{ public FrameDemo(String title)
{super(title);}
public static void main(String agrs[])
{ FrameDemo frame = new FrameDemo("Demo Frame");
第 8章 Java的 GUI设计
frame.setLocation(100,100);
frame.setSize(500,200);
frame.setVisible(true); }
}
程序的运行结果如图 8.3所示,它是一个具有标题、
大小及背景颜色的框架。
第 8章 Java的 GUI设计
图 8.3
第 8章 Java的 GUI设计
8.2.3 对话框 (Dialog)
java.awt.Dialog也是 Window的扩展类 。 与框架相同
的是, 对话框也拥有边界与标题栏, 而且也可以调整
大小;而与框架不同的是, 对话框不支持附加菜单栏,
而且对话框可以模式化属性设置, 这是窗口和框架都
不允许的 。 因此, 如果用户在程序设计过程中需要创
建一个临时窗口与用户交换信息时, 使用模式对话框
是最方便的 。 另外, AWT中还提供了 Dialog类的一个
常用的扩展类 ——FileDialog(文件对话框 )。 它可以为用
户选择一个待打开或保存的文件 。
第 8章 Java的 GUI设计
可以说对话框是介于窗口和框架之间的, 对话框和框
架相比各有特色 。 我们来看一个典型的对话框的例子 。
例 8.3 DialogDemo.java
import java.awt.*;
public class DialogDemo
{
public static void main(String agrs[])
{ Frame frame = new Frame();
第 8章 Java的 GUI设计
Dialog dialog = new Dialog(frame,"Demo Dialog",false);
dialog.setLocation(100,100);
dialog.setSize(500,100);
dialog.setVisible(true); }
}
程序运行结果如图 8.4所示 。
第 8章 Java的 GUI设计
图 8.4
第 8章 Java的 GUI设计
文件对话框是文件选择设备的一个实现 。 它有自
己的自由窗口以及窗口元素, 并且允许用户浏览文件
系统, 以及为以后的操作选择一个特定的文件 。 例如:
例 8.4 FileDialogDemo.java
import java.awt.*;
public class FileDialogDemo
{ public static void main(String[] args)
{ Frame parentFrame = new Frame();
第 8章 Java的 GUI设计
FileDialog d = new FileDialog(parentFrame,"FileDialog");
d.setVisible(true); // block here until OK selected
String fname = d.getFile(); }
}
程序的运行结果如图 8.5所示。
第 8章 Java的 GUI设计
图 8.5
第 8章 Java的 GUI设计
通常情况下, 并不需要处理 FileDialog的事件 。 上
例中, 调用 setVisible(true)将阻塞事件, 直至用户选择
OK,这时, 对话框会请求用户选择文件名, 这个信息
将作为一个 String类型返回 。
第 8章 Java的 GUI设计
8.3 AWT基本组件
8.3.1 按钮 (Button)
按钮应该是我们最熟悉的可视组件之一, 这个组
件提供了, 按下并动作, 的基本用户界面功能 。 我们
可以构造一个带文本标签的按钮, 用来告诉用户它的
作用 。 例如:
例 8.5 ButtonDemo.java
import java.awt.*;
import java.awt.event.*;
第 8章 Java的 GUI设计
public class ButtonDemo extends Frame implements
ActionListener
{ Button button;
public static void main(String[] args)
{ButtonDemo frame = new ButtonDemo();}
public ButtonDemo()
{ button = new Button("First");
button.addActionListener(this);
add(button);
第 8章 Java的 GUI设计
setTitle("Button");
setSize(130,100);
setVisible(true);}
public void actionPerformed(ActionEvent evt)
{String arg = evt.getActionCommand();
if (arg.equals("First"))
{System.out.println("Button press received.");}
}
}
程序的运行结果如图 8.6所示。
第 8章 Java的 GUI设计
图 8.6
第 8章 Java的 GUI设计
程序的运行结果如图 8.6所示 。
该例为 Button注册了一个监听器。任何实现了被注
册为监听者的 ActionListener接口的类,它的
actionPerformed()方法将在一个按钮被鼠标点击, 按下,
时被调用。
按钮被按下时调用的 getActionCommand()方法在缺
省情况下将返回触发组件的标签字符串 (此处为按键的
标签 )。我们还可以通过 setActionCommand()方法改变
动作命令和标签。
第 8章 Java的 GUI设计
8.3.2 复选框 (Checkbox)
Checkbox组件提供一种简单的, 开 /关, 输入设备, 它旁
边有一个文本标签 。 应用方式如下:
例 8.6 CheckboxDemo.java
import java.awt.*;
import java.awt.event.*;
public class CheckboxDemo extends Frame implements
ItemListener
{
public static void main(String[] args)
第 8章 Java的 GUI设计
{CheckboxDemo frame = new CheckboxDemo(); }
public CheckboxDemo()
{ setTitle("Checkbox Test");
setSize(300,100);
setLayout(new FlowLayout());
Checkbox one = new Checkbox("One",true);
Checkbox two = new Checkbox("Two",false);
Checkbox three = new Checkbox("Three",true);
one.addItemListener(this);
two.addItemListener(this);
three.addItemListener(this);
第 8章 Java的 GUI设计
add(one);
add(two);
add(three);
setVisible(true);}
public void itemStateChanged(ItemEvent evt)
{ String state = "deselected";
if (evt.getStateChange() == ItemEvent.SELECTED)
state = "selected";
System.out.println(evt.getItem()+""+state); }
}
程序运行结果如图 8.7所示 。
第 8章 Java的 GUI设计
图 8.7
第 8章 Java的 GUI设计
选取或不选取 (取消 )一个复选框的事件将被送往
ItemListener接口。所传递的 ItemEvent包含
getStateChange()方法,它根据实际情况返回
ItemEvent.DESELECTED或 ItemEvent.SELECTED。
getItem()方法将受到影响的复选框作为一个表示这个复
选框标签的 String对象返回。
程序中用到了一个布局管理器 FlowLayout。 前面我
们已经提到了布局管理器的作用, 此处为 Frame添加
FlowLayout的作用是让包含在其中的组件顺次排列 。
关于布局管理器的使用方法在 8.5节中还将详细讨论 。
第 8章 Java的 GUI设计
8.3.3 复选框组 —单选框 (Checkbox Group-Radio Button)
复选框组提供了将多个复选框作为一个互斥的集
合的方法, 因此在任何时刻, 这个集合中只有一个复
选框的值是 true。 值为 true的复选框就是当前被选中的
复选框 。 你可以使用带有一个额外的 CheckboxGroup参
数的构造函数来创建一组中的各个复选框 (正是这个
CheckboxGroup对象将各个复选框连接成一组 )。 如果
你这么做的话, 那么复选框的外观会发生改变, 而且
所有和这个复选框组相关联的复选框将表现出, 单选
框, 的行为 。 例如:
第 8章 Java的 GUI设计
例 8.7 CheckboxGroupDemo.java
import java.awt.*;
import java.awt.event.*;
public class CheckboxGroupDemo extends Frame
implements ItemListener
{
public static void main(String[] args)
{CheckboxGroupDemo frame = new
CheckboxGroupDemo();}
public CheckboxGroupDemo()
{ setTitle("Checkbox Test");
第 8章 Java的 GUI设计
setSize(300,100);
setLayout(new FlowLayout());
CheckboxGroup cbg = new CheckboxGroup();
Checkbox one = new Checkbox("One",false,cbg);
Checkbox two = new Checkbox("Two",false,cbg);
Checkbox three = new Checkbox("Three",true,cbg);
one.addItemListener(this);
two.addItemListener(this);
three.addItemListener(this);
add(one);
第 8章 Java的 GUI设计
add(two);
add(three);
setVisible(true);}
public void itemStateChanged(ItemEvent evt)
{ String state = "deselected";
if (evt.getStateChange() == ItemEvent.SELECTED)
state = "selected";
System.out.println(evt.getItem()+""+state); }
}
程序运行结果如图 8.8所示 。
第 8章 Java的 GUI设计
图 8.8
第 8章 Java的 GUI设计
8.3.4 下拉列表 (Choice)
下拉列表组件提供了一个简单的, 从列表中选取一
个, 类型的输入方式 。 例如:
例 8.8 ChoiceDemo.java
import java.awt.*;
import java.awt.event.*;
public class ChoiceDemo extends Frame implements
ItemListener
{
public static void main(String[] args)
{ChoiceDemo frame = new ChoiceDemo(); }
第 8章 Java的 GUI设计
public ChoiceDemo()
{ setSize(100,150);
Choice choice = new Choice();
choice.add("First");
choice.add("Second");
choice.add("Third");
choice.addItemListener(this);
add(choice);
setVisible(true);}
第 8章 Java的 GUI设计
public void itemStateChanged(ItemEvent evt)
{ String state = "deselected";
if (evt.getStateChange() == ItemEvent.SELECTED)
state = "selected";
System.out.println(evt.getItem()+""+state); }
}
程序运行结果如图 8.9所示 。
第 8章 Java的 GUI设计
图 8.9
第 8章 Java的 GUI设计
点击下拉列表组件时, 它会显示一个列表, 列表
中包含了所有加入其中的条目 。 注意所加入的条目是
String对象 。 ItemListener接口用来观察下拉列表组件的
变化, 其细节和复选框的相同 。
第 8章 Java的 GUI设计
8.3.5 标签 (Label)
一个标签对象显示一行静态文本 。 程序员可以改
变文本, 但用户不能改变 。 标签没有任何特殊的边框
和装饰 。 例如:
例 8.9 LabelDemo.java
import java.awt.*;
public class LabelDemo extends Frame
{
public static void main(String[] args)
{ LabelDemo frame = new LabelDemo();
frame.setSize(100,50);
第 8章 Java的 GUI设计
图 8.10
第 8章 Java的 GUI设计
Label label = new Label("Hello");
frame.add(label);
frame.setVisible(true); }
}
程序运行结果如图 8.10所示 。
标签通常不处理事件,但也可以按照和画布相同
的方式来处理事件。也就是说,只有调用了
requestFocus()方法后,才能可靠地检取击键事件。
第 8章 Java的 GUI设计
8.3.6 文本域 (Textfield)
文本域是一个单行的文本输入设备, 通常用于获
取一行用户输入的字符, 如用户名, 密码的输入等 。
例如:
例 8.10 TextfieldDemo.java
import java.awt.*;
import java.awt.event.*;
public class TextfieldDemo extends Frame implements
ActionListener
{
第 8章 Java的 GUI设计
public static void main(String[] args)
{TextfieldDemo frame = new TextfieldDemo(); }
public TextfieldDemo()
{ setSize(300,100);
setLayout(new GridLayout(2,2));
Label l1 = new Label("User:");
TextField user = new TextField("");
user.addActionListener(this);
Label l2 = new Label("Password:");
TextField pass = new TextField("");
pass.addActionListener(this);
add(l1);
第 8章 Java的 GUI设计
add(user);
add(l2);
add(pass);
setVisible(true); }
public void actionPerformed(ActionEvent evt)
{ String arg = evt.getActionCommand();
System.out.println(""+arg); }
}
第 8章 Java的 GUI设计
因为只允许有一行文字,所以当按下 Enter或
Return键时,ActionListener可以通过 actionPerformed()
检测到这个事件。如果需要,还可以增加其他的组件
监听者。
除了注册一个 ActionListener,你还可以注册一个
TextListener来接收关于个别击键的通知。它的回调方
法是 textValueChanged(TextEvent)。程序运行结果如图
8.11所示。
第 8章 Java的 GUI设计
图 8.11
第 8章 Java的 GUI设计
8.3.7 文本区 (TextArea)
文本区是一个多行多列的文本输入设备 。 你可以
用 setEditable(boolean)将它设置成只读的 。 文本区将显
示水平和垂直的滚动条 。 下面这个范例创建了一个 4行
× 30字符的文本, 最初它含有 "Hello!"字符 。
例 8.11 TextAreaDemo.java
import java.awt.*;
import java.awt.event.*;
public class TextAreaDemo extends Frame implements
TextListener
第 8章 Java的 GUI设计
{
public static void main(String[] args)
{
TextAreaDemo frame = new TextAreaDemo();}
public TextAreaDemo()
{
setSize(300,100);
TextArea area = new TextArea("Hello!",4,30);
area.addTextListener(this);
add(area);
第 8章 Java的 GUI设计
setVisible(true);}
public void textValueChanged(TextEvent evt)
{ System.out.println(""+evt); }
}
用 addTexListener指定的监听者将以和文本域相同
的方式接收到关于击键的通知 。
可以给文本区增加一般的组件监听者, 然而, 由
于文本是多行的, 按下 Enter键将导致把另一个字符送
入缓冲 。 如果你需要识别, 输入的结束,, 你可以在
文本区旁放置一个, 应用, 或, 确认, 按钮, 以便用
户指明, 输入的结束, 。 程序运行结果如图 8.12所示 。
第 8章 Java的 GUI设计
图 8.12
第 8章 Java的 GUI设计
8.3.8 列表 (List)
一个列表可将各个文本选项显示在一个区域中,
这样就可以在同时看到若干个条目 。 列表可以滚动,
并支持单选和多选两种模式 。 例如:
例 8.12 ListDemo.java
import java.awt.*;
import java.awt.event.*;
public class ListDemo extends Frame
implements ItemListener
{ public static void main(String[] args)
第 8章 Java的 GUI设计
{ListDemo frame = new ListDemo(); }
public ListDemo()
{ setSize(100,200);
List list = new List(4,true);
list.add("First");
list.add("Second");
list.add("Third");
list.add("Fourth");
list.addItemListener(this);
add(list);
第 8章 Java的 GUI设计
setVisible(true);}
public void itemStateChanged(ItemEvent evt)
{ String state = "deselected";
if (evt.getStateChange() == ItemEvent.SELECTED)
state = "selected";
System.out.println(evt.getItem()+""+state); }
}
构造函数的数值参数定义了按可见列计算的列表
高度 。 这个值也可能被布局管理器覆盖 。 一个值为 true
的布尔型参数表明这个列表允许用户作多个选择 。
第 8章 Java的 GUI设计
选取或取消一个条目时, AWT将一个 ItemEvent的
实例送往列表 。 用户双击滚动列表中的一个条目时,
单选模式和多选模式的列表都会产生一个 ActionEvent,
根据每个平台的约定来决定列表中的条目是否被选取 。
对于 Unix/Motif环境, 单击会加亮列表中的一个条目,
只有双击才会触发列表事件 (选取条目 )。
程序运行结果如图 8.13所示 。
第 8章 Java的 GUI设计
图 8.13
第 8章 Java的 GUI设计
8.3.9 画布 (Canvas)
画布提供了一个空白 (背景色 )的空间 。 除非你用
setSize()显式地定义它的大小, 否则它的大小就是 0× 0。
画布的空间可以用来绘图, 显示文本, 接收键盘
或鼠标的输入 。 通常, 画布用来提供一个一般的绘图
空间或者为客户组件提供工作区域 。
画布可以, 监听, 所有适用于一个普通组件的事
件。特别地,你还可能想增加 KeyListener、
MouseMotionListener和 MouseListener对象,以允许以
某种方式对用户输入作出反应。
第 8章 Java的 GUI设计
注:如要在画布中接收键盘事件, 必须调用画布
的 requestFocus()方法 。 如果缺少这个步骤, 一般不能
将击键, 导向, 画布 。 而且键盘事件会送往另一个组
件, 或整个地丢失 。
下面是画布的一个范例 。 用户每击一次键, 这个程
序就改变一次画布的颜色 。
例 8.13 CanvasDemo.java
import java.awt.*;
import java.awt.event.*;
import java.util.*;
第 8章 Java的 GUI设计
public class CanvasDemo extends Canvas implements
KeyListener
{ int index;
Color colors[] = {Color.red,Color.green,Color.blue };
public static void main(String args[])
{ Frame f = new Frame("Canvas");
CanvasDemo mc = new CanvasDemo();
f.add(mc,BorderLayout.CENTER);
f.setSize(150,150);
第 8章 Java的 GUI设计
mc.requestFocus();
mc.addKeyListener(mc);
f.setVisible(true); }
public void paint(Graphics g)
{ g.setColor(colors[index]);
g.fillRect(0,0,getSize().width,getSize().height);}
第 8章 Java的 GUI设计
图 8.14
第 8章 Java的 GUI设计
public void keyTyped(KeyEvent ev)
{ index++;
if (index == colors.length) index =0;
repaint(); }
public void keyPressed(KeyEvent ev) { }
public void keyReleased(KeyEvent ev) { }
}
程序运行结果如图 8.14所示 。
第 8章 Java的 GUI设计
8.3.10 面板 (Panel)
像 Frame一样, Panel提供空间来连接任何 GUI组件,
包括其他面板 。 每个面板都可以有它自己的管理程序 。
一旦一个面板对象被创建, 为了能被看见, 必须将它
添加到窗口或框架对象上 。 用 Container类中的 add()方
式可以做到这一点 。
下面的程序创建了一个小的黄色面板,并将它加
到了一个框架对象上。
第 8章 Java的 GUI设计
例 8.14 FrameWithPanel.java
import java.awt.*;
public class FrameWithPanel extends Frame
{
public FrameWithPanel (String str)
{super (str);}
public static void main (String args[])
{ FrameWithPanel fr = new FrameWithPanel ("Frame with
Panel");
Panel pan = new Panel();
第 8章 Java的 GUI设计
fr.setSize(200,200);
fr.setBackground(Color.blue);
fr.setLayout(null);
pan.setSize (100,100);
pan.setBackground(Color.yellow);
fr.add(pan);
fr.setVisible(true);}
}
程序的运行结果如图 8.15所示 。
第 8章 Java的 GUI设计
图 8.15
第 8章 Java的 GUI设计
8.3.11 滚动面板 (ScrollPane)
滚动面板提供了一种不能作为自由窗口的通用容
器, 它总是和一个容器相关联 (例如框架 )。 滚动面板提
供了到一个更大的区域的视窗以及操纵这个视窗的滚
动条 。 例如:
例 8.15 ScrollPaneDemo.java
import java.awt.*;
import java.awt.event.*;
public class ScrollPaneDemo
{
第 8章 Java的 GUI设计
public static void main(String[] args)
{ Frame f = new Frame("ScrollPane");
Panel p = new Panel();
ScrollPane sp = new ScrollPane();
p.setLayout(new GridLayout(3,4));
for (int i = 0; i < 12; i++)
{p.add(new Button("Button"+i));}
sp.add(p);
f.add(sp,"Center");
f.setSize(150,150);
f.setVisible(true); }
}
第 8章 Java的 GUI设计
图 8.16
第 8章 Java的 GUI设计
程序运行结果如图 8.16所示 。
滚动面板创建和管理滚动条, 并持有一个组件 。
它不能控制自己所用的布局管理器, 但可以将一个面
板加入到滚动面板中, 配置面板的布局管理器, 并在
那个面板中放置你的组件 。
通常, 滚动面板上的事件均通过滚动面板所包含
的组件进行处理 。
第 8章 Java的 GUI设计
8.4 菜 单
菜单与其他组件有一个重要的不同:不能将菜单
添加到一般的容器中, 而且不能使用布局管理器对它
们进行布局, 只能将菜单加到一个菜单容器中 。 你可
以通过使用 setMenuBar()方法将菜单放到一个框架中,
从而启动一个菜单, 树, 之后, 便可以将菜单加到菜
单条中, 并将菜单或菜单项加到菜单中 。
弹出式菜单是一个例外, 因为它们可以以浮动窗
口形式出现, 因此不需要布局 。
第 8章 Java的 GUI设计
8.4.1 帮助菜单
菜单条的一个特性是你可以将其中一个菜单指定
为帮助菜单 。 这可以用 setHelpMenu(Menu) 来做到, 但
必须先加入到菜单条中, 它才会和本地平台的帮助菜
单以同样的方式被处理 。 对于 X/Motif类型的系统, 被
设定为帮助菜单的菜单条将显示在菜单条的最右边 。
第 8章 Java的 GUI设计
8.4.2 菜单条 (MenuBar)
一个菜单条组件是一个水平菜单 。 它只能加入到
一个框架中, 并成为所有菜单树的根 。 在一个时刻,
一个框架可以显示一个菜单条 。 然而, 你可以根据程
序的状态修改菜单条, 这样就可以在不同的时刻显示
不同的菜单 。 例如:
Frame f = new Frame("MenuBar");
MenuBar mb = new MenuBar();
f.setMenuBar(mb);
菜单条不支持监听者 。 作为普通菜单行为的一部
分, 在菜单条的区域中发生的预期事件会被自动处理 。
第 8章 Java的 GUI设计
8.4.3 菜单 (Menu)
菜单组件提供了一个基本的下拉式菜单 。 它可以
加入到一个菜单条或者另一个菜单中 。 例如:
MenuBar mb = new MenuBar();
Menu m1 = new Menu("File");
Menu m2 = new Menu("Edit");
Menu m3 = new Menu("Help");
mb.add(m1);
mb.add(m2);
第 8章 Java的 GUI设计
mb.setHelpMenu(m3);
f.setMenuBar(mb);
生成的菜单如图 8.17所示 。
第 8章 Java的 GUI设计
图 8.17
第 8章 Java的 GUI设计
8.4.4 菜单项 (MenuItem)
菜单项组件是菜单树的文本, 叶, 结点 。 它们通
常被加入到菜单中, 以构成一个完整的菜单 。 例如:
例 8.16 MenuBarDemo.java
import java.awt.*;
import java.awt.event.*;
public class MenuBarDemo extends
Frame implements ActionListener
{
public static void main(String[] args)
第 8章 Java的 GUI设计
{MenuBarDemo frame = new MenuBarDemo(); }
public MenuBarDemo()
{ setSize(200,200);
MenuBar mb = new MenuBar();
Menu m1 = new Menu("File");
MenuItem mi1 = new MenuItem("New");
mi1.addActionListener(this);
MenuItem mi2 = new MenuItem("Load");
mi2.addActionListener(this);
第 8章 Java的 GUI设计
MenuItem mi3 = new MenuItem("Save");
mi3.addActionListener(this);
MenuItem mi4 = new MenuItem("Quit");
mi4.addActionListener(this);
m1.add(mi1);
m1.add(mi2);
m1.add(mi3);
m1.add(mi4);
Menu m2 = new Menu("Edit");
Menu m3 = new Menu("Help");
第 8章 Java的 GUI设计
mb.add(m1);
mb.add(m2);
mb.add(m3);
setMenuBar(mb);
setVisible(true); }
public void actionPerformed(ActionEvent evt)
{ String arg = evt.getActionCommand();
System.out.println(arg); }
}
第 8章 Java的 GUI设计
通常, 将一个 ActionListener加入到一个菜单项对象
中, 以提供菜单的行为 。 程序的运行结果如图 8.18所示 。
第 8章 Java的 GUI设计
图 8.18
第 8章 Java的 GUI设计
8.4.5 复选菜单项 (CheckboxMenuItem)
复选菜单项是一个可操作的的菜单项, 可以在菜
单上有选项 (“开, 或, 关, )。 来看如下例子:
例 8.17 MenuBarDemo.java
import java.awt.*;
import java.awt.event.*;
public class MenuBarDemo extends
Frame implements ItemListener
{ public static void main(String[] args)
第 8章 Java的 GUI设计
{MenuBarDemo frame = new MenuBarDemo();}
public MenuBarDemo()
{ setSize(200,200);
MenuBar mb = new MenuBar();
Menu m1 = new Menu("File");
MenuItem mi1 = new MenuItem("Save");
CheckboxMenuItem mi2 = new
CheckboxMenuItem("Persistent");
mi2.addItemListener(this);
m1.add(mi1);
m1.add(mi2);
第 8章 Java的 GUI设计
Menu m2 = new Menu("Edit");
mb.add(m1);
mb.add(m2);
setMenuBar(mb);
setVisible(true); }
public void itemStateChanged(ItemEvent evt)
{ String state = "deselected";
if(evt.getStateChange()== ItemEvent.SELECTED)
第 8章 Java的 GUI设计
state = "selected";
System.out.println(evt.getItem()+" "+state); }
}
可以用 ItemListener接口来监视复选菜单。因此当
复选框状态发生改变时,就会调用 itemStateChanged()
方法。程序运行结果如图 8.19所示。
第 8章 Java的 GUI设计
图 8.19
第 8章 Java的 GUI设计
8.4.6 弹出式菜单 (PopupMenu)
弹出式菜单提供了一种独立的菜单, 它可以在任
何组件上显示 。 你可以将菜单条目和菜单加入到弹出
式菜单中去 。 例如:
例 8.18 PopupMenuDemo.java
import java.awt.*;
import java.awt.event.*;
第 8章 Java的 GUI设计
public class PopupMenuDemo extends Frame implements
ActionListener
{ Button b;
PopupMenu pm;
public static void main(String[] args)
{PopupMenuDemo frame = new PopupMenuDemo(); }
public PopupMenuDemo()
{ setSize(100,100);
第 8章 Java的 GUI设计
setLayout(new BorderLayout());
b = new Button("Popup");
b.addActionListener(this);
pm = new PopupMenu("Popup");
MenuItem s = new MenuItem("Save");
MenuItem l = new MenuItem("Load");
pm.add(s);
pm.add(l);
add(b,BorderLayout.CENTER);
add(pm);
第 8章 Java的 GUI设计
setVisible(true);}
public void actionPerformed(ActionEvent
evt){pm.show(b,10,10);}
}
为了显示弹出式菜单, 需要一个组件的引用, 作
为 x和 y坐标轴的起点 。 通常, 要使用组件的触发器来
激活弹出式菜单 。 在上面这个范例中, 触发器是 Button
b。 程序运行结果如图 8.20所示 。
注:弹出式菜单必须加入到一个“父”组件中,
这与将组件加入到容器中是不同的。在上面这个范例
中,弹出式菜单被加入到了周围的框架中。
第 8章 Java的 GUI设计
图 8.20
第 8章 Java的 GUI设计
8.5 布 局 管 理 器
8.5.1 Flow Layout
Flow布局管理器用于对组件逐行地定位, 每完成一
行, 一个新行便又开始 。 与其他布局管理器不一样的
是, Flow布局管理器不限制它所管理的组件的大小,
允许它们有自己的最佳大小 。
第 8章 Java的 GUI设计
Flow布局管理器允许将组件左对齐或右对齐 。 如
果想在组件之间创建一个更大的最小间隔, 可以规定
一个界限 。 当用户对由 Flow布局管理的区域进行缩放
时, 布局就发生变化, 如图 8.21所示 。
下面的例子就是如何用类容器的 setLayout()方法来
创建 Flow布局对象并安装它们的 。
setLayout(new FlowLayout(int align,int hgap,int vgap));
对齐的值必须是 FlowLayout.LEFT,
FlowLayout.RIGHT或 FlowLayout.CENTER。例如:
setLayout(new FlowLayout(FlowLayout.RIGHT,20,40));
第 8章 Java的 GUI设计
图 8.21
当用户改变窗口的大小时
第 8章 Java的 GUI设计
例 8.19构造并安装一个新的 Flow布局, 它带有规定
好的居中对齐方式和一个缺省的 5单位的水平和垂直间
隙 。 这个模块代码将几个按钮添加到框架中的一个
Flow布局中 。
例 8.19 FlowLayoutDemo.java
import java.awt.*;
public class FlowLayoutDemo
{ private Frame f;
private Button button1,button2,button3;
第 8章 Java的 GUI设计
public static void main (String args[])
{ FlowLayoutDemo mflow = new
FlowLayoutDemo();mflow.go();}
public void go()
{ f = new Frame ("Flow Layout");
f.setLayout(new FlowLayout());
button1 = new Button("Ok");
button2 = new Button("Open");
button3 = new Button("Close");
f.add(button1);
第 8章 Java的 GUI设计
f.add(button2);
f.add(button3);
f.setSize (100,100);
f.setVisible(true);}
}
运行结果如图 8.22所示 。
第 8章 Java的 GUI设计
图 8.22
第 8章 Java的 GUI设计
8.5.2 BorderLayout
Border布局管理器为在一个 Panel或 Window中放置
组件提供一个更复杂的方案 。 Border布局管理器包括
五个明显的区域:东, 南, 西, 北, 中 。
北占据面板的上方,东占据面板的右侧,等等。
中间区域是在东、南、西、北都填满后剩下的区域。
当窗口垂直延伸时,东、西、中区域延伸;而当窗口
水平延伸时,南、北、中区域延伸,如图 8.23所示。
Border布局管理器是用于 Dialog和 Frame的缺省布
局管理器。
第 8章 Java的 GUI设计
图 8.23
当用户改变窗口的大小时
第 8章 Java的 GUI设计
注:当窗口缩放时, 按钮相应的位置不变化, 但
其大小改变 。
可以用从 Container类继承的 setLayout()方法来将布
局设定为 Border布局 。 下面的代码表示出了 Border布局
管理器的特性 。
第 8章 Java的 GUI设计
例 8.20 BordLayoutDemo.java
import java.awt.*;
public class BordLayoutDemo
{ private Frame f;
private Button bn,bs,bw,be,bc;
public static void main(String args[])
{ BordLayoutDemo bord = new
BordLayoutDemo();bord.go(); }
public void go()
{ f = new Frame("Border Layout");
第 8章 Java的 GUI设计
bn = new Button("B1");
bs = new Button("B2");
be = new Button("B3");
bw = new Button("B4");
bc = new Button("B5");
f.add(bn,BorderLayout.NORTH);
第 8章 Java的 GUI设计
f.add(bs,BorderLayout.SOUTH);
f.add(be,BorderLayout.EAST);
f.add(bw,BorderLayout.WEST);
f.add(bc,BorderLayout.CENTER);
f.setSize (200,200);
f.setVisible(true); }
}
程序运行结果如图 8.24所示 。
第 8章 Java的 GUI设计
图 8.24
第 8章 Java的 GUI设计
setLayout(new BorderLayout())构造并安装一个新
Border布局, 在组件之间没有间隙 。
setLayout(new BorderLayout(int hgap,int vgap)构
造并安装一个 Border布局,在由 hgap和 vgap规定的组
件之间有规定的间隙。在布局管理器中,组件必须被
添加到指定的区域。区域名称拼写要正确,尤其是在
选择不使用常量 (如 add(button,"Center"))而使用
add(button,BorderLayout.CENTER)时,拼写与大写很
关键。
第 8章 Java的 GUI设计
可以使用 Border布局管理器来产生布局, 且带有在缩
放时在一个方向, 另一方向或双方向上都延伸的元素 。
可以仅将单个组件添加到 Border布局管理器五个区域
的每一个当中 。 如果添加不止一个, 只有最后一个看得
见 。 后面的示例将演示如何用中间容器来允许不止一个
组件被放在单个 Border布局管理器区域的空间里 。
注:布局管理器给予南, 北组件最佳高度, 并强迫
它们与容器一样宽, 但对于东, 西组件, 给予最佳宽度,
而高度受到限制 。
第 8章 Java的 GUI设计
8.5.3 GridLayout
Grid布局管理器为放置组件提供了灵活性。它先用
许多行和栏来创建管理程序,然后组件就填充到由管
理程序规定的单元中。比如,由语句 new
GridLayout(3,2)创建的有三行两栏的 Grid布局能产生如
图 8.25所示的六个单元。
第 8章 Java的 GUI设计
图 8.25
当用户改变窗口大小时
第 8章 Java的 GUI设计
Grid布局管理器总是忽略组件的最佳大小 。 所有
单元的宽度是相同的, 是根据单元数对可用宽度进行
平分而定的 。 同样地, 所有单元的高度也是相同的,
是根据行数对可用高度进行平分而定的 。
将组件添加到网格中的命令决定它们占有的单元 。
单元的行数是从左到右填充, 就像文本一样, 而页是
从上到下由行填充 。 下面是一个 GridLayout应用的示例 。
第 8章 Java的 GUI设计
例 8.21 GridLayoutDemo.java
import java.awt.*;
public class GridLayoutDemo
{ private Frame f;
private Button b1,b2,b3,b4,b5,b6;
public static void main(String args[])
{ GridLayoutDemo grid = new GridLayoutDemo();
grid.go(); }
第 8章 Java的 GUI设计
public void go()
{ f = new Frame("Grid example");
f.setLayout (new GridLayout (3,2));
b1 = new Button("1");
b2 = new Button("2");
b3 = new Button("3");
b4 = new Button("4");
b5 = new Button("5");
b6 = new Button("6");
f.add(b1);
f.add(b2);
第 8章 Java的 GUI设计
f.add(b3);
f.add(b4);
f.add(b5);
f.add(b6);
f.pack();
f.setVisible(true); }
}
运行结果如图 8.26所示 。
setLayout(new GridLayout())创建并安装一个 Grid布局,
每行中的每个组件有一个栏缺省 。
第 8章 Java的 GUI设计
setLayout(new GridLayout(int rows,int cols))创建并
安装一个带有规定好行数和栏数的 Grid布局 。 对布局
中所有组件所给的大小一样 。
setLayout(new GridLayout(int rows,int cols,int hgap,
int vgap)创建并安装一个带有规定好行数和栏数的网格
布局 。 布局中所有组件所给的大小一样 。 hgap和 vgap
规定组件间各自的间隙:水平间隙放在左右两边及栏
与栏之间;垂直间隙放在顶部, 底部及每行之间 。
第 8章 Java的 GUI设计
图 8.26
第 8章 Java的 GUI设计
8.5.4 GridBagLayout
最复杂的布局管理器是 GridBagLayout。
GridBagLayout与 GridLayout有点相似,它也是将组件
排在格子里,但是 GridBagLayout在网格的基础上提供
更复杂的布局。它允许单个组件在一个单元中不填满
整个单元,而只是占用最佳大小,也允许单个组件扩
展成不止一个单元,并且可以用任意顺序加入组件。
第 8章 Java的 GUI设计
为了使用 GridBagLayout,必须构造一个
GridBagConstraints对象。 GridBagConstraints用于指定
如何用 GridBagLayout放置组件。 GridBagConstraints对
象包含一些重要的参数,以指定组件的放置方式,这
些参数的含义如下:
● gridx,gridy,gridwidth和 gridheight参数 。 这四个
参数用于指定组件在网格中的位置 。 gridx和 gridy值用
于指定组件左上角的坐标; gridwidth和 gridheight决定
组件将占用多少行和列 。
第 8章 Java的 GUI设计
● 加权参数 weightx和 weighty。 GridBagLayout内的每
个区域都必须设置它的加权参数, 即 weightx和 weighty。
如果将权值设置为 0,那么这个区域就不会在那个方向
上扩张或收缩, 超出它的初始大小 。
● fill和 anchor参数。 fill参数用于指定组件在单元格内
进行伸缩时的填充方式,该参数可以有四种参数值:
GridBagConstraints.NONE(不伸缩 )、
GridBagConstraints.HORIZONTAL(水平伸缩 )、
GridBagConstraints.VERTICAL(垂直伸缩 )和
GridBagConstraints.
第 8章 Java的 GUI设计
BOTH(水平和垂直同时伸缩 )。 anchor参数用于指
定组件在一个单元格内靠在它的什么部位。可选
GridBagConstraints.CENTER(居中 )、
GridBagConstraints.NORTH(北 )、
GridBagConstraints.NORTHEAST(东北 )、
GridBagConstraints.EAST(东 )、
GridBagConstraints.SOUTHEAST(东南 )、
GridBagConstraints.SOUTH(南 )、
GridBagConstraints.SOUTHWEST(西南 )、
GridBagConstraints.WEST(西 )或者
GridBagConstraints.NORTHWEST(西北 )。
第 8章 Java的 GUI设计
● 填充参数 insets,ipadx和 ipady。 insets参数用于设置
沿单元格边界的外部填充空白区域 。 ipadx和 ipady则用
于指定在环绕组件四周的单元格内部填充空白区域 。
下面我们通过一个例子学习如何使用 GridBagLayout。
例 8.22 GridBagLayoutDemo.java
import java.awt.*;
public class GridBagLayoutDemo extends Frame
{ Canvas c;
Choice cb;
第 8章 Java的 GUI设计
TextArea ta;
TextField tf;
Button b1,b2,b3;
GridBagLayout gbLayout;
GridBagConstraints gbConstraints;
public static void main(String args[])
{GridBagLayoutDemo demo = new
GridBagLayoutDemo();}
public GridBagLayoutDemo()
{ gbLayout = new GridBagLayout();
第 8章 Java的 GUI设计
setLayout(gbLayout);
gbConstraints = new GridBagConstraints();
ta = new TextArea("TextArea",5,10);
cb = new Choice();
cb.addItem("Linden");
cb.addItem("Birch");
cb.addItem("Ceder");
tf = new TextField("TextField");
b1 = new Button("Button 1");
b2 = new Button("Button 2");
第 8章 Java的 GUI设计
b3 = new Button("Button 3");
c = new Canvas();
c.setBackground(Color.blue);
c.setSize(10,5);
// textarea
gbConstraints.weightx = 0;
gbConstraints.weighty = 0;
gbConstraints.fill = GridBagConstraints.BOTH;
addComponent(ta,gbLayout,gbConstraints,0,0,1,3);
第 8章 Java的 GUI设计
// button b1
gbConstraints.fill = GridBagConstraints.HORIZONTAL;
addComponent(b1,gbLayout,gbConstraints,0,1,2,1);
// choice button
addComponent(cb,gbLayout,gbConstraints,2,1,2,1);
// button b2
gbConstraints.weightx = 1000;
gbConstraints.weighty = 1;
gbConstraints.fill = GridBagConstraints.BOTH;
addComponent(b2,gbLayout,gbConstraints,1,1,1,1);
第 8章 Java的 GUI设计
// button b3
gbConstraints.weightx = 0;
gbConstraints.weighty = 0;
gbConstraints.fill = GridBagConstraints.BOTH;
addComponent(b3,gbLayout,gbConstraints,1,2,1,1);
// text field
addComponent(tf,gbLayout,gbConstraints,3,0,2,1);
// canvas
addComponent(c,gbLayout,gbConstraints,3,2,1,1);
setSize(250,150);
第 8章 Java的 GUI设计
setVisible(true);}
private void addComponent(Component c,GridBagLayout g,
GridBagConstraints gc,int row,int column,int width,
int height)
{ gc.gridx = column;
gc.gridy = row;
gc.gridwidth = width;
gc.gridheight = height;
g.setConstraints(c,gc);
add(c); }
} 程序运行结果如图 8.27所示 。
第 8章 Java的 GUI设计
图 8.27
第 8章 Java的 GUI设计
8.5.5 CardLayout
Card布局管理器能将界面看作一系列的卡, 其中
的一个在任何时候都可见 。 用 add()方法可将卡添加到
Card布局中 。 Card布局管理器的 show()方法响应请求转
换到一个新卡中 。 下例就是一个带有 5张卡的框架 。
例 8.23 CardLayoutDemo.java
import java.awt.*;
import java.awt.event.*;
public class CardLayoutDemo implements
MouseListener
第 8章 Java的 GUI设计
{ Panel p1,p2,p3,p4,p5;
Label l1,l2,l3,l4,l5;
CardLayout myCard;
Frame f;
public static void main (String args[])
{ CardLayoutDemo ct = new CardLayoutDemo();
ct.init(); }
public void init()
{ f = new Frame ("Card Test");
myCard = new CardLayout();
f.setLayout(myCard);
p1 = new Panel();
第 8章 Java的 GUI设计
p2 = new Panel();
p3 = new Panel();
p4 = new Panel();
p5 = new Panel();
l1 = new Label("This is the first Panel");
p1.setBackground(Color.yellow);
p1.add(l1); p1.addMouseListener(this);
l2 = new Label("This is the second Panel");
p2.setBackground(Color.green);
p2.add(l2); p2.addMouseListener(this);
l3 = new Label("This is the third Panel");
第 8章 Java的 GUI设计
p3.setBackground(Color.magenta);
p3.add(l3); p3.addMouseListener(this);
l4 = new Label("This is the fourth Panel");
p4.setBackground(Color.white);
p4.add(l4); p4.addMouseListener(this);
l5 = new Label("This is the fifth Panel");
p5.setBackground(Color.cyan);
p5.add(l5); p5.addMouseListener(this);
f.add(p1,"First");
第 8章 Java的 GUI设计
f.add(p2,"Second");
f.add(p3,"Third");
f.add(p4,"Fourth");
f.add(p5,"Fifth");
myCard.show(f,"First");
f.setSize (200,200);
f.setVisible(true); }
public void mouseClicked(MouseEvent e)
{myCard.next(f);}
public void mousePressed(MouseEvent e){}
第 8章 Java的 GUI设计
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
程序运行结果如图 8.28所示 (鼠标点击左面板将视
图转换到右面板, 等等 )。
第 8章 Java的 GUI设计
图 8.28
第 8章 Java的 GUI设计
8.5.6 不使用布局管理器
除了以上介绍的各种布局管理器, Java也允许程序
员不使用布局管理器, 而是直接指定各个组件的位置 。
不使用布局管理器的例子如下:
例 8.24 NoLayoutDemo
import java.awt.*;
public class NoLayoutDemo
{ public static void main(String[] args)
{ Frame f = new Frame();
f.setLayout(null);
第 8章 Java的 GUI设计
Choice cb = new Choice();
cb.addItem("item 1");
cb.addItem("item 2");
cb.addItem("item 3");
Button b1 = new Button("Button 1");
Button b2 = new Button("Button 2");
Button b3 = new Button("Button 3");
f.add(cb); f.add(b1);
f.add(b2); f.add(b3);
b1.setBounds(25,25,60,26);
第 8章 Java的 GUI设计
b2.setBounds(100,40,90,22);
b3.setBounds(220,30,70,55);
cb.setBounds(50,80,70,18);
f.setSize(300,150);
f.setVisible(true); }}
第 8章 Java的 GUI设计
程序中用 setBounds()方法设置每个组件的位置和大
小 。 也许大家觉得这种方法才是我们常见的方式, 看
起来更简单和方便, 但是请注意, Java的目的是通用
于各种平台, 不使用布局管理器显然无法做到这一点 。
另外, 不使用布局管理器的界面, 在用于改变窗口大
小时是不会自动调整位置和大小的, 这显然不是一种
友好的界面设置方式 。 程序的运行结果如图 8.29所示 。
第 8章 Java的 GUI设计
图 8.29
第 8章 Java的 GUI设计
8.6 Java AWT事件处理机制
如果用户在用户界面层执行了一个动作 (鼠标点击
和按键 ),这将导致一个事件的发生 。 事件是描述发生
了什么的对象 。 存在各种不同类型的事件类用来描述
各种类型的用户交互 。 事件源是一个事件的产生者 。
例如, 在 Button组件上点击鼠标会产生以这个 Button 为
源的一个 ActionEvent。 这个 ActionEvent实例是一个对
象, 它包含关于刚才所发生的那个事件的信息的对象 。
事件处理器就是一个接收事件, 解释事件并处理用户
交互的方法 。
第 8章 Java的 GUI设计
8.6.1 事件的层次关系
从 JDK1.1开始, 事件接收和处理的方法发生了重
要的改变 。 JDK1.0采用的是层次事件模型, 而 JDK1.1
以上版本则采用的是委托事件模型 。
层次模型是基于容器的 。 事件先发送到组件, 然
后沿容器层次向上传播 。 没有被组件处理的事件会自
动地继续传播到组件的容器 。
第 8章 Java的 GUI设计
图 8.30
F r a m e
B u t t o n
P an e l
A c t i o n e v e n t
第 8章 Java的 GUI设计
例如, 图 8.30中, Button对象 (包含在一个 Frame上
的 Panel中 )上的鼠标点击首先向 Button发送一个动作事
件 。 如果它没有被 Button处理, 这个事件会被送往
Panel,如果它在那儿仍然没有被处理, 这个事件会被
送往 Frame。
这种模型有一个显著的优点:它简单, 而且非常
适合面向对象的编程环境 。 总的来说, 所有的组件都
继承了 java.awt.Component 类, 而 handleEvent() 就在
java.awt.Component类中 。 然而, 这种模型也存在缺点:
第 8章 Java的 GUI设计
(1) 事件只能由产生这个事件的组件或包含这个组
件的容器处理 。 这个限制违反了面向对象编程的一个
基本原则:功能应该包含在最合适的类中 。 而最适合
处理事件的类往往并不是源组件的容器层次中的成员 。
(2) 该模型中,大量的 CPU周期浪费在处理不相关
的事件上。任何对于程序来说不相关或者并不重要的
事件会沿容器层次一路传播,直到最后被抛弃。处理
的过程中不存在一种简单的方法来过滤事件。
第 8章 Java的 GUI设计
(3) 为了处理事件, 你必须定义接收这个事件的组
件的子类, 或者在基容器创建一个庞大的 handleEvent()
方法 。
委托事件模型是在 JDK1.1中引入的 。 在这个模型
中, 事件被送往产生这个事件的组件, 然而, 注册一
个或多个称为监听者的类取决于每一个组件, 这些类
包含事件处理器, 用来接收和处理这个事件 。 采用这
种方法, 事件处理器可以安排在与源组件分离的对象
中 。 监听者就是实现了 Listener接口的类 。
第 8章 Java的 GUI设计
事件是只向注册的监听者报告的对象 。 每个事件
都有一个对应的监听者接口, 规定哪些方法必须在适
合接收那种类型的事件的类中定义 。 实现了定义那些
方法的接口的类可以注册为一个监听者, 如图 8.31所示 。
第 8章 Java的 GUI设计
图 8.31
F r a m e
a c t i o n P e r f o r m e d ( A c t i o n E v e n t e ) {
…
}
A c t i o n h a n d l e rB u t t o n
P a n e l
P a n e l a n d F r a m e
e v e n t h a n d l e r s
A c t i o n e v e n t
第 8章 Java的 GUI设计
这种方法有以下优点:
(1) 事件不会被意外地处理 。 在层次模型中, 一个
事件可能传播到容器, 并在非预期的层次被处理 。
(2) 有可能创建并使用适配器 (adapter)类对事件动
作进行分类 。
(3) 委托模型有利于把工作分布到各个类中 。
(4) 新的事件模型提供对 JavaBeans的支持 。
这种方法也有一个缺点:尽管当前的 JDK支持委托
模型和 JDK1.0事件模型,但不能混合使用 JDK1.0和
JDK1.1。
第 8章 Java的 GUI设计
8.6.2 事件类型
我们已经介绍了在单一类型事件上, 下文中从组
件接收事件的通用机制 。 许多事件类在 java.awt.event包
中, 也有一些事件类在 API的其他地方 。 图 8.32显示了
事件的类层次关系 。
对于每类事件,都有一个接口,这个接口必须由
想接收这个事件的类的对象实现。这个接口还要求定
义一个或多个方法,当发生特定的事件时,就会调用
这些方法。表 8.4列出了这些 (事件 )类型,并给出了每
个类型对应的接口名称,以及所要求定义的方法。这
些方法的名称是易于记忆的,名称表示了会引起这个
方法被调用的源或条件。
第 8章 Java的 GUI设计
图 8.32
j a v a, u t i l,E v e n t O b j e c t
j a v a, a w t, A W T E v e n t
j a v a, b e a n s, b e a n C o n t e x t
A c t i o n E v e n t
A d j u s t m e n t E v e n t
C o m p o n e n t E v e n t
I t e m E v e n t
T e x t E v e n t
C o n t a i n e r E v e n t
F o c u s E v e n t
I n p u t E v e n t
W i n d o w E v e n t
K e y E v e n t
Mo u s e E v e n t
B e a n C o n t e x t E v e n t
.,.
第 8章 Java的 GUI设计
表 8.4 方法类型和接口
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)
第 8章 Java的 GUI设计
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)
第 8章 Java的 GUI设计
Window WindowListener
windowClosing(WindowEvent)
windowOpened(WindowEvent)
windowIconified(WindowEvent)
WindowDeiconified(WindowEvent)
WindowClosed(WindowEvent)
WindowActivated(WindowEvent)
WindowDeactivated(WindowEvent)
Container ContainerListener
componentAdded(ContainerEvent)
ComponentRemoved(ContainerEvent)
Text TextListener TextValueChanged(TextEvent)
第 8章 Java的 GUI设计
8.6.3 事件处理过程
本节将通过一个范例说明事件的处理过程 。 它将跟
踪鼠标被按下时, 鼠标的移动情况 (鼠标拖动 ),还将监
测当鼠标没有按下时, 鼠标的移动情况 (鼠标移动 )。
当鼠标按下或没有按下时,移动鼠标产生的事件
会被实现了 MouseMotionListener接口的类的对象检取。
这个接口要求定义两个方法,mouseDragged()和
mouseMoved()。即使你只对鼠标拖动感兴趣,也必须
提供这两个方法,但是 mouseMoved()的体可以是空的。
第 8章 Java的 GUI设计
要检取其他鼠标事件,包括鼠标点击,必须定义
MouseListener接口。这个接口包括若干个事件,即
mouseEntered,mouseExited,mousePressed、
mouseReleased和 mouseClicked。
发生鼠标或键盘事件时, 有关鼠标的位置和所按
下的键的信息可以从事件中得到, 代码如下 。
第 8章 Java的 GUI设计
例 8.25 ListenDemo.java
import java.awt.*;
import java.awt.event.*;
public class ListenDemo
implements MouseMotionListener,MouseListener
{ private Frame f;
private TextField tf;
第 8章 Java的 GUI设计
public static void main(String args[])
{ ListenDemo two = new ListenDemo(); two.go(); }
public void go()
{ f = new Frame("Two listeners example");
f.add (new Label("Click and drag the
mouse"),BorderLayout.NORTH);
tf = new TextField(30);
f.add (tf,BorderLayout.SOUTH);
f.addMouseMotionListener(this);
f.addMouseListener (this);
f.setSize(300,200);
第 8章 Java的 GUI设计
f.setVisible(true); }
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";
第 8章 Java的 GUI设计
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) {}
}
运行以上程序可看到如图 8.33所示界面 。 当在窗口
中拖动鼠标时, 底端的 TextField中将显示鼠标的当前
位置 。
第 8章 Java的 GUI设计
图 8.33
第 8章 Java的 GUI设计
● 定义多了多个接口
这个类由代码:
implements MouseMotionListener,MouseListener
声明 。 声明多个接口时, 可以用逗号隔开 。
第 8章 Java的 GUI设计
● 监听多个源
如果调用方法:
f.addMouseListener(this);
f.addMouseMotionListener(this);
则两种类型的事件都会引起 ListenDemo类中的方
法被调用 。 一个对象可以, 监听, 任意数量的事件源;
它的类只需要实现所要求的接口 。
第 8章 Java的 GUI设计
8.6.4 事件 Adapters(适配器 )
一旦指定一个类实现了某个事件监听器接口, 就
必须实现这个监听器接口的所有方法, 否则你只能将
你的类定义为抽象类而无法定义这个类的实例 。 从上
面的例子我们可以看到, 实现每个 Listener接口的所有
方法的工作量均是非常大的, 尤其是 MouseListener接
口和 ComponentListener接口 。
以 MouseListener接口为例,它定义了如下方法:
第 8章 Java的 GUI设计
① mouseClicked(MouseEvent)
② mouseEntered(MouseEvent)
③ mouseExited(MouseEvent)
④ mousePressed(MouseEvent)
⑤ mouseReleased(MouseEvent)
为了方便起见,Java语言提供了 Adapters类,用来
实现含有多个方法的类。这些 Adapters类中的方法是空
的。你可以继承 Adapters类,而且只需重写你所需要的
方法。
第 8章 Java的 GUI设计
public class MouseClickHandler extends MouseAdapter
{ // We just need the mouseClick handler,so we use
// the Adapter to avoid having to write all the
// event handler methods
public void mouseClicked(MouseEvent e)
{ // Do something with the mouse click..,}
}
第 8章 Java的 GUI设计
8.7 Swing 基 础
从 JDK1.2开始, AWT添加了被称为 Swing的新 GUI
库 。 Swing是基于 AWT基本结构创建的二级用户界面
工具集, Swing提供了一整套 GUI组件 。 为了保证可移
植性, 它是完全用 Java语言编写的 。
第 8章 Java的 GUI设计
8.7.1 Swing的层次结构
与 AWT比较, Swing提供了更完整的组件, 引入了
许多新的特性和能力 。 Swing API是围绕着实现 AWT各
个部分的 API构筑的 。 这保证了所有早期的 AWT组件
仍然可以使用 。 AWT采用了与特定平台相关的实现,
而绝大多数 Swing组件却不是这样做的, 因此, Swing
的外观和感觉是可客户化和可插的 。
第 8章 Java的 GUI设计
图 8.34显示了 JFC各个部分之间的相互关系 。
Java2D,Accessibility,Drag & Drop和 Accessibility API
是 AWT和 JFC的一部分, 但它们不属于 Swing。 这是因
为, 这些组件使用了一些本地代码, 而 Swing却不是这
样的 。
Swing是围绕着一个称为 JComponent的新组件构建
的, 而 JComponent则由 AWT的容器类扩展而来 。
图 8.35说明了 Swing组件的层次结构。
第 8章 Java的 GUI设计
图 8.34
第 8章 Java的 GUI设计
图 8.35
j a v a,a w t,C o n t a i n e r
c o m, s u n, j a v a, s w i n g, J C o m p o n e n t
J T e x t C o m p o n e n t
A b s t r a c t B u t t o n
J P a n e l
J C o m b o B o x
J L a b e l
J L a y e r e d P a n e
J L i s t
J T o o l B a r
J M e n u B a r
J P o p u p Me n u
J P a n e
J S c r o l l B a r
J S c r o l l P a n e
J S l i d e r
J T a b l e
J S e p a r a t o r
J T r e e
J P r o g r e s s B a r
J R o o t P a n e
J S p l i t P a n e
J T a b b e d P a n e
J T e x t F i e l d
H t m l E d i t o r K i t
J T e x t A r e a
J B u t t o n
J M e n u I t e m
J T o g g l e B u t t o n
J C h e c k B o x M e n u I t e m
J M e n u
J R a d i o B u t t o n M e n u I t e m
J R a d i o B u t t o n
J C h e c k B o x
J P a s s w o r d F i e l d
第 8章 Java的 GUI设计
8.7.2 Swing组件
Swing组件主要为文本处理, 按钮, 标签, 列表,
面板, 组合框, 滚动条, 滚动面板, 菜单, 表格和树
提供了组件 。 其中的一些组件如图 8.36所示 。
第 8章 Java的 GUI设计
图 8.36
JApplet JButton
第 8章 Java的 GUI设计
图 8.36
JComboBo JOptionPane
第 8章 Java的 GUI设计
图 8.36
JList JLabel
第 8章 Java的 GUI设计
JScrollPane JTable
图 8.36
第 8章 Java的 GUI设计
图 8.36
JScrollBar JSlider
第 8章 Java的 GUI设计
图 8.36
JToolti Jtree
第 8章 Java的 GUI设计
由于这些 Swing组件的功能和用法和 AWT组件基本
相似, 所以这里不再详细说明, 大家使用时可以参考
Sun公司提供的 JDK API文档 。
Swing都是作为 JComponent的子类来实现的, 它从
JComponent继承了如下功能:
● 边框:你可以用 setBorder()方法来指定在组件周围
显示的边框 。 还可用一个 EmptyBorder的实例来指定一
个组件在其周围留有一定的额外空间 。
第 8章 Java的 GUI设计
● 双缓冲:双缓冲可以改善一个频繁被改变的组件的
外观 。 现在, 你不需要编写双缓冲代码, 因为 Swing已
为你提供了 。 缺省情况下, Swing组件是双缓冲的 。
● 提示框:通过用 setToolTipText()方法来指定一个字
符串, 你可以提供给用户有关某个组件的帮助信息 。
当光标暂停在组件上时, 所指定的字符串就会在组件
附近的一个小窗口中显示出来 。
第 8章 Java的 GUI设计
● 键盘导航:使用 registerKeyboardAction()方法, 你可
以让用户以键盘代替鼠标来操作 GUI。 用户为启动一
个动作所必须按下的修饰键与字符的组合, 由一个
KeyStroke对象来表示 。
第 8章 Java的 GUI设计
● 应用程序范围的可插式外观和感觉:每个 Java应用
程序在运行时刻有一个 GUIManager对象,它用于确定
运行时刻 Swing组件的外观和感觉。由于安全性的限制,
你可以通过调用 UIManager.setLookAndFeel()方法选择
所有 Swing组件的外观和感觉。在你所看见的东西背后,
每个 JComponent对象都有一个对应的 ComponentGUI对
象,它用来执行所有关于该 JComponent的绘制、事件
处理、大小判定等任务。
第 8章 Java的 GUI设计
8.7.3 建立 Swing窗口
Swing程序用 JFrame 对象实现了它们的窗口 。
JFrame类是 AWT Frame类的一个子类 。 它还加入了一
些 Swing所独有的特性 。 例如:
例 8.26 SwingDemo.java
import java.awt.*;
import javax.swing.*;
public class SwingDemo extends JFrame
{
第 8章 Java的 GUI设计
public static void main(String[] args)
{ SwingDemo frame = new SwingDemo();
frame.setSize(300,100);
frame.setVisible(true); }
第 8章 Java的 GUI设计
public SwingDemo()
{ Container pane = getContentPane();
JPanel p = new JPanel();
p.setLayout(new FlowLayout());
JScrollPane sp = new JScrollPane(p);
JButton b1 = new JButton("Button 1");
JButton b2 = new JButton("Button 2");
p.add(b1);
第 8章 Java的 GUI设计
p.add(b2);
JTextField tf = new JTextField("Hello!",10);
p.add(tf);
JCheckBox one = new JCheckBox("One",true);
JCheckBox two = new JCheckBox("Two",false);
JCheckBox three = new JCheckBox("Three",true);
p.add(one);
第 8章 Java的 GUI设计
p.add(two);
p.add(three);
pane.add(sp); }
}
第 8章 Java的 GUI设计
这段代码与使用 Frame的代码十分相似, Swing的
各种组件用法也和 AWT的对应组件基本相同, 只是功
能更为强大, 组件也更多样 (因为 Swing组件的用法和
前面介绍的 AWT组件基本相同, 这里不再一一举例,
大家可以参考前面的例子, 参看 Java的 API文档自己学
习使用 )。 惟一的区别在于, 你不能将组件加入到
JFrame中, 只能将组件加入到 JFrame的 content pane中,
或者提供一个新的 content pane。
第 8章 Java的 GUI设计
一个 content pane是一个包含除菜单条 (如果有的话 )
外所有框架的可视组件的容器。要获得一个 JFrame的
content pane,可使用 getContentPane()方法。要设置它
的 content pane(如前面例所示 )可使用 setContentPane()方
法。程序的运行结果如图 8.37所示。
第 8章 Java的 GUI设计
图 8.37
第 8章 Java的 GUI设计
8.1 AWT基础
8.2 窗口类
8.3 AWT基本组件
8.4 菜单
8.5 布局管理器
8.6 Java AWT事件处理机制
8.7 Swing基础
第 8章 Java的 GUI设计
8.1 AWT 基 础
开发图形界面的应用程序时, 需要用到 AWT(抽象
图形工具集 )。 AWT是 Java开发工具包 (JDK)的一部分,
是 Java基本类 (JFC)的核心 。 AWT的作用是给用户提供
基本的界面组件, 如:窗口, 按键, 菜单等 。 此外,
AWT还提供事件处理结构, 支持剪贴板, 数据传输和
图像操作 。
第 8章 Java的 GUI设计
在 Java 1.0中,AWT最初的设计目标是提供一个用
来建立图形用户界面的独立平台,可以让程序员组建
一个通用的 GUI,使其在所有平台上都能正常显示。
遗憾的是,这个目标并没有很好的实现,但幸运的是,
这种情况从 Java 1.1以后得到了大的改进。从 Java 1.2开
始,AWT添加了被称为,Swing”的新 GUI库。
第 8章 Java的 GUI设计
Swing是基于 AWT基本结构创建的二级用户界面工
具集 。 与旧的 AWT相比, Swing提供更加丰富的组件
集, Swing中所提供的组件集几乎可以替代所有 AWT
中原有的组件 。 由此, 许多人也许会产生 Swing是
AWT的替代物的误解, 而实际上 Swing是基于 AWT之
上创建的 。 因此, 为了准确的掌握 Swing组件集的工作
方式, 必须首先掌握 AWT组件的行为及其工作原理 。
第 8章 Java的 GUI设计
8.1.1 java.awt包简介
AWT在 java.awt包中提供, 表 8.1列出了 AWT中的
Java软件包 。
AWT包含四个主要的类:组件类 (Component),容
器类 (Container),图形类 (Graphics)和布局管理器类
(LayoutManager和 LayoutManager2)。
第 8章 Java的 GUI设计
● Component(组件 )类 —— 菜单, 按键, 列表等组件的抽
象基本类 。
● Container(容器 )类 —— 扩展 Component的抽象基本类 。
由 Container 派 生 的类 有 Panel, Applet, Window,
Dialog和 Frame类等 。 在容器中, 可以包含多个组件 。
● Graphics(图形类 )类 —— 定义组件内图形操作的基本类 。
每个组件都有一个相关的图形对象 。
● LayoutManager(布局管理器 )类 —— 定义容器中组件的
位置和尺寸的接口 。 Java中定义了几种默认的布局管
理器 。
第 8章 Java的 GUI设计
表 8.1 AWT中的软件包
软 件 包 描 述
java.awt 基本组件实用工具
java.awt.accessibility 辅助技术
java.awt.color 颜色和颜色空间
java.awt.datatransfer 支持剪贴板和数据传输
java.awt.dnd 支持拖放
java.awt.event 事件类和监听器
java.awt.font 2D API字体软件包
java.awt.geom,2D API几何软件包
第 8章 Java的 GUI设计
java.awt.im 引入方法
java.awt.image 图像处理工具包
java.awt.peer 同位体组件, 界面包
java.awt.print 支持打印 2D API
java.awt.swing Swing组件
java.awt.test 测试 AWT方法有限子集的独立 applet
第 8章 Java的 GUI设计
组件, 容器和布局管理器构成了 AWT中的简单基
础关系:容器中可以包含组件;所有的容器都包含布
局管理器 (java.awt.Container类除外 ),用来指定容器中
组件的位置和形状 。 图形类则提供在组件中显示文本
和图形的方法 。 AWT中的许多操作都发生在组件, 容
器和布局管理器之间 。
第 8章 Java的 GUI设计
8.1.2 AWT组件类层次
组件是构成 AWT的基础 。 AWT中包括大量的组件,
其中大约有一半的类由 java.awt.Component类扩展而来,
所以, Component和它所支持的类是 AWT的基础 。
java.awt.Component类是一个抽象类, 它为其派生类
提供了许多功能 。 例如, 一个组件可以有以下成员:图
形对象, 位置, 尺寸, 父容器, 前景和背景色, 最小 /最
大和首选尺寸等 。
第 8章 Java的 GUI设计
Java语言中, 面板 (Panel),滚动条 (Scrollbar),按
键 (Button),标签 (Label)等等用户界面组件一般都派生
自 java.awt.Component类 。 图 8.1是一些主要的 AWT组
件的结构层次 。
第 8章 Java的 GUI设计
图 8.1
B u t t o nC o m p o n e n t
T e x t C o m p o n e n t
S c r o l l b a r
L a b e l
C h e c k b o x
C a n v a s
C o n t a i n e r
W i n d o w
P a n e l A p p l e t
F r a m e
D i a l o g
T e x t F i e l d
T e x t A r e a
第 8章 Java的 GUI设计
8.1.3 容器和布局管理器
从 java.awt.Container类扩展的类称为容器,
Container也是一个从 Component扩展的抽象类。顾名思
义,容器就是用来包含组件的,一个容器可以包含多
个组件,也可以使用容器将相关组件关联在一起,成
为一个整体。合理的使用容器可以简化图形界面的设
计,而且对于组件的显示安排也很有用。表 8.2列出了
从 java.awt.Container类派生的 AWT容器类。后面我们
还会详细说明这些容器的使用。
第 8章 Java的 GUI设计
表 8.2 Container的子类
子类 说 明
Applet Panel.Applet的扩展, 使所有 Applet的超类
Dialog 对话框 (可模式化或非模式化 Window的扩展 )
FieldDialog 用于选择文件的对话框
Frame Window的扩展, 应用程序的容器, 可以有菜单和标题栏
Panel Container的扩展, 简单的容器
ScrollPane 滚动组件
Window Container的扩展, 没有菜单或边界, 是 Frame和 Dialog的超类
第 8章 Java的 GUI设计
容器只能记录包含的组件, 而布局管理器则负责
指定容器中组件的位置和大小 。 Java的布局管理器只
需要确定组件和其他组件的相对位置, 而不需要决定
它的坐标, 这样的安排令与平台无关的用户界面更易
于实现 。 AWT中提供了五种布局管理器:
● BorderLayout:该布局管理器将容器划分为东,
南, 西, 北, 中五个区域, 当添加组件到容器中时,
要指明将容器放置到哪一个区域中 。
第 8章 Java的 GUI设计
● CarderLayout:该布局管理器将容器当作一个卡片栈,
添加到容器中的每个组件都被放置在一个单独的卡片
上, 但每次只能显示一张卡片 。
● FlowLayout:该布局管理器将添加到容器中的组件按
从上到下, 从左到右的顺序依次排列 。
● GridLayout:该布局管理器将容器分成相同尺寸的网
格, 将添加到容器中的组件按从左到右, 从上到下的
顺序放置在每一个网格中 。
第 8章 Java的 GUI设计
● GridBagLayout:该布局管理器也是将容器分成网
格,它和 GridLayout不一样的是,一个组件可以占据不
止一个网格的位置。
关于布局管理器将在后面的章节中进行更深入的
讨论,现在最重要的是站在高层次上理解布局管理器
是如何协助容器管理组件的布局的。
第 8章 Java的 GUI设计
8.1.4 可视组件的始祖类 ——Component类
前面已经提到, Component类是大多数组件的超
类, 而 Component类则直接继承 Object类 。 Component
类是一个抽象类, 所以是不能直接使用, 它为子类提
供了非常 多的虚 拟方 法 。 我 们先简 单介绍 一下
Component类提供的一些主要方法:
● public boolean contains(int x,int y)
● public boolean contains(Point p)
以上两个方法用于检查 (x,y)或者对象 p这个点是
否落在组件的范围之内 (其中, (x,y)坐标是相对于此组
件的左上角的 ),是则返回 true,否则返回 false。
第 8章 Java的 GUI设计
● public Color getBackground()
返回组件的背景颜色, 若组件没有设置背景颜色,
则会返回其父组件 (包含该组件的组件 )的背景颜色 。
● public void setBackground(Color c)
设置组件的背景颜色, 若参数 c的值为 null,则会
将背景颜色设为其父组件的背景颜色 。
● public Rectangle getBounds()
返回组件外框矩形的范围, 这个范围定义了组件
的宽, 高和相对其容器的坐标位置 。
第 8章 Java的 GUI设计
● public void setBounds(int x,int y,int width,int height)
● public void setBounds(Rectangle r)
设置组件的位置, 宽度和高度, 可用于移动组件
或改变其大小 。 除非此组件的容器没有使用布局管理
器, 否则这两个方法不生效 。
● public Component getComponentAt(int x,int y)
● public Component getComponentAt(Point p)
第 8章 Java的 GUI设计
判断组件或组件中的子组件 (包含的组件 )中, 是否
有一个包含 (x,y)这个点的组件, 是则返回该组件, 否
则返回 null。 该方法只检查一级子组件, 如果点 (x,y)在
其子组件的子组件中, 则只会返回该组件第一级的子
组件 。
● public Cursor getCursor()
返回组件的鼠标光标对象 。 如果该组件没有设置
鼠标光标, 则返回其父组件的鼠标光标 。
第 8章 Java的 GUI设计
● public void setCursor(Cursor cursor)
设置组件的鼠标光标, 例如将 Button的光标改为手
指, 将 Panel的光标改为放大镜等, 当鼠标移动到这些
对象上时会产生相应的变化 。 若参数为 null,则设成和
父组件的光标一样 。
● public Font getFont()
返回组件的字体, 若组件没有设置字体, 则返回
其父组件的字体 。
● public void setFont(Font f)
设置组件的字体, 若参数 f的值为 null,则会采用其
父组件的字体 。
第 8章 Java的 GUI设计
● public Color getForeground()
返回组件的前景颜色, 若组件没有设置前景颜色,
则会返回其父组件的前景颜色 。
● public void setForeground(Color c)
设置组件的前景颜色, 若参数 c的值为 null,则会将
前景颜色设为其父组件的前景颜色 。
● public Graphics getGraphics()
所有可视组件都有属于自己的 Graphics对象可供画
图, 此方法返回该组件的 Graphics对象 。 但要注意, 若
此组件还没有显示在屏幕上则会返回 null。
第 8章 Java的 GUI设计
● public Point getLocation()
● public int getX()
● public int getY()
这三个方法用于返回组件矩形外框的左上角的坐
标,这个坐标也是相对于其父组件而言的。 getX()和
getY()的作用与 getLocation().x和 getLocation().y或
getBounds().x和 getBounds().y一样,但推荐使用 getX()
和 getY(),因为这两个方法无需内存分配。
第 8章 Java的 GUI设计
● public void setLocation(int x,int y)
● public void setLocation(Point p)
移动该组件到左上角的由 (x,y)或点对象 p所指定的
新位置, 坐标也是相对于其父组件的 。 须注意的是, 如
果此组件使用了 layout manager,这两个方法将不生效 。
● public Container getParent()
返回该组件的父组件, 若没有父组件将返回 null。
第 8章 Java的 GUI设计
● public Dimension getSize()
● public int getWidth()
● public int getHeight()
返回该组件的高度和宽度 。 与 getX()和 getY()一样,
应该使用 getWidth()和 getHeight()而不是 getSize().width
和 getSize().height 或 getBounds().width 和
getBounds().height。
● public void setSize(int width,int height)
第 8章 Java的 GUI设计
● public void setSize(Dimentsion d)
改变组件的高度与宽度 。 如果该组件使用了 layout
manager,这两个方法将无效 。
● public boolean isEnabled()
检查组件当前状态, 可用状态则返回 true,否则返
回 false。 组件的可用状态指组件可以接收用户输入及
产生事件的状态, 如 Windows中变灰的按键, 就是非
可用状态的 。
● public void setEnabled(boolean b)
更改组件的状态为可用或不可用 。
第 8章 Java的 GUI设计
● public boolean isVisible()
检查当组件的父组件为可见的时候, 此组件是否
为可见, 是则返回 true,否则返回 false。 除了顶层窗口
(如 Frame)外, 组件默认初始为可见 。
● public void setVisible(boolean b)
根据参数 b的值改变窗口状态为可见或隐藏 。
第 8章 Java的 GUI设计
● public void paint(Graphics g)
在屏幕上绘制组件, 当组件第一次显示或者需要
重绘时该方法会自动被调用 。 如果需要改变某个基本
组件的样式, 可以通过重载这个函数来实现 。 重载这
个函数不需要调用 super.paint(g)。
● public void repaint()
将组件重画一遍 。 当一个组件需要重画时, 如从
隐藏变为可见, 或者被其他窗口遮住后那个窗口移开
了, 系统就会自动调用该方法, 该方法又立即调用
update()方法 。
第 8章 Java的 GUI设计
● public void update(Graphics g)
该方法的作用是将组件占据的矩形范围清成背景
色, 然后调用 paint()方法重画这个组件 。 在动画技术中,
经常需要用到一个叫 Double Buffering(双缓冲技术 )的技
巧来避免画面的闪烁, 这就需要重载 update()和 paint()
这两个方法来实现 。 应注意的是, 重载 update()方法的
时候, 应该要调用 super.update()方法或者手动调用
paint()方法 。
● public String toString()
返回该组件的文字描述 。
第 8章 Java的 GUI设计
8.2 窗 口 类
AWT提供了三个在屏幕上显示窗口的组件:
Window,Frame和 Dialog。 这三个组件都用于显示窗口,
而且相互之间的区别也不明显, 因此有时候很难确定
到底使用哪个组件更好 。 为了帮助大家区分它们的不
同用法, 表 8.3列出了各组件的属性特征 。
第 8章 Java的 GUI设计
表 8.3 Window,Frame与 Dialog组件的属性
属 性 Window Frame Dialog
模式化 不是 不是 不是 (可设置 )
可调大小 不可 可 可
标题栏 无 有 有
边界 无 有 有
标题 无 有 有
菜单栏 无 有 无
焦点管理器 有 有 有
警告字符串 有 有 有
图表 无 有 无
定位到框架 可 不可 可
第 8章 Java的 GUI设计
8.2.1 窗口 (Window)
java.awt.Window是三个窗口组件中最基本的组件,
它实际上是 Frame与 Dialog组件的超类 。 窗口组件没有
边界, 标题栏与菜单栏, 而且大小不可以调整 。 其次,
如果用户在程序设计过程中, 需要利用悬浮在其他组
件上方的无边界矩形框显示信息, 则窗口是最佳选择 。
常用窗口实现的界面包括:产品信息的封面 (如 Outlook
等软件启动时, 显示在屏幕中间且几秒后自动消失的
封面窗口 ),提示帮助信息 (如使用金山词霸等软件时,
移动鼠标到某个英文单词上时自动弹出的解释信息 )等 。
第 8章 Java的 GUI设计
下面我们通过一个例子来学习如何使用窗口类:
例 8.1 FrameDemo.java
import java.awt.*;
public class SplashDemo extends Frame
{ Window window;
static public void main(String[] args)
{SplashDemo frame = new SplashDemo(); }
public SplashDemo()
{ window = new Window(this);
第 8章 Java的 GUI设计
Dimension scmSize =
Toolkit.getDefaultToolkit().getScreenSize();
int width = 300;
int height = 200;
window.setLocation(scmSize.width/2-
(width/2),scmSize.height/2-(height/2));
window.setSize(width,height);
window.show();
第 8章 Java的 GUI设计
window.toFront();
try { Thread.currentThread().sleep(3000);}
catch (Exception e) {e.printStackTrace();}
window.dispose();
System.exit(0); }
}
这是个使用 Window的窗口在屏幕上显示一个矩形
窗口类的实例, 这个窗口没有边界, 标题栏与菜单栏,
在屏幕上停留 3秒后自动消失 。 如果在窗口中加载一幅
图片, 则能实现一个类似 Outlook的封面窗口 (在窗口中
加载图片的方法我们将在第 9章中学习 )。
第 8章 Java的 GUI设计
程序中用到了工具类的方法
Toolkit.getDefaultToolkit().getScreenSize()。 Toolkit类是
一个包含许多有用的本地工具方法的类。
getScreenSize()方法的作用是取得显示器的像素尺寸。
程序的运行结果如图 8.2所示。
第 8章 Java的 GUI设计
图 8.2
第 8章 Java的 GUI设计
8.2.2 框架 (Frame)
java.awt.Frame是 Window的一个子类, 它是带有标
题栏和边界的窗口, 而且允许调整大小 。 另外, 用户
还可以为框架附加一个菜单栏 。 用户在程序设计过程
中, 当程序窗口需要图表化或者需要包含菜单栏时,
则可以选择使用框架组件 。
构造一个框架后, 可以用 add()方法来给框架添加
组件 。 框架的缺省布局管理器属性是 BorderLayout。 可
以用 setLayout()方式来改变布局管理器属性 。
第 8章 Java的 GUI设计
框架类中的 Frame(String) 构造方法创建一个由
String规定标题的新的不可见的框架对象 。
例 8.2 FrameDemo.java
import java.awt.*;
public class FrameDemo extends Frame
{ public FrameDemo(String title)
{super(title);}
public static void main(String agrs[])
{ FrameDemo frame = new FrameDemo("Demo Frame");
第 8章 Java的 GUI设计
frame.setLocation(100,100);
frame.setSize(500,200);
frame.setVisible(true); }
}
程序的运行结果如图 8.3所示,它是一个具有标题、
大小及背景颜色的框架。
第 8章 Java的 GUI设计
图 8.3
第 8章 Java的 GUI设计
8.2.3 对话框 (Dialog)
java.awt.Dialog也是 Window的扩展类 。 与框架相同
的是, 对话框也拥有边界与标题栏, 而且也可以调整
大小;而与框架不同的是, 对话框不支持附加菜单栏,
而且对话框可以模式化属性设置, 这是窗口和框架都
不允许的 。 因此, 如果用户在程序设计过程中需要创
建一个临时窗口与用户交换信息时, 使用模式对话框
是最方便的 。 另外, AWT中还提供了 Dialog类的一个
常用的扩展类 ——FileDialog(文件对话框 )。 它可以为用
户选择一个待打开或保存的文件 。
第 8章 Java的 GUI设计
可以说对话框是介于窗口和框架之间的, 对话框和框
架相比各有特色 。 我们来看一个典型的对话框的例子 。
例 8.3 DialogDemo.java
import java.awt.*;
public class DialogDemo
{
public static void main(String agrs[])
{ Frame frame = new Frame();
第 8章 Java的 GUI设计
Dialog dialog = new Dialog(frame,"Demo Dialog",false);
dialog.setLocation(100,100);
dialog.setSize(500,100);
dialog.setVisible(true); }
}
程序运行结果如图 8.4所示 。
第 8章 Java的 GUI设计
图 8.4
第 8章 Java的 GUI设计
文件对话框是文件选择设备的一个实现 。 它有自
己的自由窗口以及窗口元素, 并且允许用户浏览文件
系统, 以及为以后的操作选择一个特定的文件 。 例如:
例 8.4 FileDialogDemo.java
import java.awt.*;
public class FileDialogDemo
{ public static void main(String[] args)
{ Frame parentFrame = new Frame();
第 8章 Java的 GUI设计
FileDialog d = new FileDialog(parentFrame,"FileDialog");
d.setVisible(true); // block here until OK selected
String fname = d.getFile(); }
}
程序的运行结果如图 8.5所示。
第 8章 Java的 GUI设计
图 8.5
第 8章 Java的 GUI设计
通常情况下, 并不需要处理 FileDialog的事件 。 上
例中, 调用 setVisible(true)将阻塞事件, 直至用户选择
OK,这时, 对话框会请求用户选择文件名, 这个信息
将作为一个 String类型返回 。
第 8章 Java的 GUI设计
8.3 AWT基本组件
8.3.1 按钮 (Button)
按钮应该是我们最熟悉的可视组件之一, 这个组
件提供了, 按下并动作, 的基本用户界面功能 。 我们
可以构造一个带文本标签的按钮, 用来告诉用户它的
作用 。 例如:
例 8.5 ButtonDemo.java
import java.awt.*;
import java.awt.event.*;
第 8章 Java的 GUI设计
public class ButtonDemo extends Frame implements
ActionListener
{ Button button;
public static void main(String[] args)
{ButtonDemo frame = new ButtonDemo();}
public ButtonDemo()
{ button = new Button("First");
button.addActionListener(this);
add(button);
第 8章 Java的 GUI设计
setTitle("Button");
setSize(130,100);
setVisible(true);}
public void actionPerformed(ActionEvent evt)
{String arg = evt.getActionCommand();
if (arg.equals("First"))
{System.out.println("Button press received.");}
}
}
程序的运行结果如图 8.6所示。
第 8章 Java的 GUI设计
图 8.6
第 8章 Java的 GUI设计
程序的运行结果如图 8.6所示 。
该例为 Button注册了一个监听器。任何实现了被注
册为监听者的 ActionListener接口的类,它的
actionPerformed()方法将在一个按钮被鼠标点击, 按下,
时被调用。
按钮被按下时调用的 getActionCommand()方法在缺
省情况下将返回触发组件的标签字符串 (此处为按键的
标签 )。我们还可以通过 setActionCommand()方法改变
动作命令和标签。
第 8章 Java的 GUI设计
8.3.2 复选框 (Checkbox)
Checkbox组件提供一种简单的, 开 /关, 输入设备, 它旁
边有一个文本标签 。 应用方式如下:
例 8.6 CheckboxDemo.java
import java.awt.*;
import java.awt.event.*;
public class CheckboxDemo extends Frame implements
ItemListener
{
public static void main(String[] args)
第 8章 Java的 GUI设计
{CheckboxDemo frame = new CheckboxDemo(); }
public CheckboxDemo()
{ setTitle("Checkbox Test");
setSize(300,100);
setLayout(new FlowLayout());
Checkbox one = new Checkbox("One",true);
Checkbox two = new Checkbox("Two",false);
Checkbox three = new Checkbox("Three",true);
one.addItemListener(this);
two.addItemListener(this);
three.addItemListener(this);
第 8章 Java的 GUI设计
add(one);
add(two);
add(three);
setVisible(true);}
public void itemStateChanged(ItemEvent evt)
{ String state = "deselected";
if (evt.getStateChange() == ItemEvent.SELECTED)
state = "selected";
System.out.println(evt.getItem()+""+state); }
}
程序运行结果如图 8.7所示 。
第 8章 Java的 GUI设计
图 8.7
第 8章 Java的 GUI设计
选取或不选取 (取消 )一个复选框的事件将被送往
ItemListener接口。所传递的 ItemEvent包含
getStateChange()方法,它根据实际情况返回
ItemEvent.DESELECTED或 ItemEvent.SELECTED。
getItem()方法将受到影响的复选框作为一个表示这个复
选框标签的 String对象返回。
程序中用到了一个布局管理器 FlowLayout。 前面我
们已经提到了布局管理器的作用, 此处为 Frame添加
FlowLayout的作用是让包含在其中的组件顺次排列 。
关于布局管理器的使用方法在 8.5节中还将详细讨论 。
第 8章 Java的 GUI设计
8.3.3 复选框组 —单选框 (Checkbox Group-Radio Button)
复选框组提供了将多个复选框作为一个互斥的集
合的方法, 因此在任何时刻, 这个集合中只有一个复
选框的值是 true。 值为 true的复选框就是当前被选中的
复选框 。 你可以使用带有一个额外的 CheckboxGroup参
数的构造函数来创建一组中的各个复选框 (正是这个
CheckboxGroup对象将各个复选框连接成一组 )。 如果
你这么做的话, 那么复选框的外观会发生改变, 而且
所有和这个复选框组相关联的复选框将表现出, 单选
框, 的行为 。 例如:
第 8章 Java的 GUI设计
例 8.7 CheckboxGroupDemo.java
import java.awt.*;
import java.awt.event.*;
public class CheckboxGroupDemo extends Frame
implements ItemListener
{
public static void main(String[] args)
{CheckboxGroupDemo frame = new
CheckboxGroupDemo();}
public CheckboxGroupDemo()
{ setTitle("Checkbox Test");
第 8章 Java的 GUI设计
setSize(300,100);
setLayout(new FlowLayout());
CheckboxGroup cbg = new CheckboxGroup();
Checkbox one = new Checkbox("One",false,cbg);
Checkbox two = new Checkbox("Two",false,cbg);
Checkbox three = new Checkbox("Three",true,cbg);
one.addItemListener(this);
two.addItemListener(this);
three.addItemListener(this);
add(one);
第 8章 Java的 GUI设计
add(two);
add(three);
setVisible(true);}
public void itemStateChanged(ItemEvent evt)
{ String state = "deselected";
if (evt.getStateChange() == ItemEvent.SELECTED)
state = "selected";
System.out.println(evt.getItem()+""+state); }
}
程序运行结果如图 8.8所示 。
第 8章 Java的 GUI设计
图 8.8
第 8章 Java的 GUI设计
8.3.4 下拉列表 (Choice)
下拉列表组件提供了一个简单的, 从列表中选取一
个, 类型的输入方式 。 例如:
例 8.8 ChoiceDemo.java
import java.awt.*;
import java.awt.event.*;
public class ChoiceDemo extends Frame implements
ItemListener
{
public static void main(String[] args)
{ChoiceDemo frame = new ChoiceDemo(); }
第 8章 Java的 GUI设计
public ChoiceDemo()
{ setSize(100,150);
Choice choice = new Choice();
choice.add("First");
choice.add("Second");
choice.add("Third");
choice.addItemListener(this);
add(choice);
setVisible(true);}
第 8章 Java的 GUI设计
public void itemStateChanged(ItemEvent evt)
{ String state = "deselected";
if (evt.getStateChange() == ItemEvent.SELECTED)
state = "selected";
System.out.println(evt.getItem()+""+state); }
}
程序运行结果如图 8.9所示 。
第 8章 Java的 GUI设计
图 8.9
第 8章 Java的 GUI设计
点击下拉列表组件时, 它会显示一个列表, 列表
中包含了所有加入其中的条目 。 注意所加入的条目是
String对象 。 ItemListener接口用来观察下拉列表组件的
变化, 其细节和复选框的相同 。
第 8章 Java的 GUI设计
8.3.5 标签 (Label)
一个标签对象显示一行静态文本 。 程序员可以改
变文本, 但用户不能改变 。 标签没有任何特殊的边框
和装饰 。 例如:
例 8.9 LabelDemo.java
import java.awt.*;
public class LabelDemo extends Frame
{
public static void main(String[] args)
{ LabelDemo frame = new LabelDemo();
frame.setSize(100,50);
第 8章 Java的 GUI设计
图 8.10
第 8章 Java的 GUI设计
Label label = new Label("Hello");
frame.add(label);
frame.setVisible(true); }
}
程序运行结果如图 8.10所示 。
标签通常不处理事件,但也可以按照和画布相同
的方式来处理事件。也就是说,只有调用了
requestFocus()方法后,才能可靠地检取击键事件。
第 8章 Java的 GUI设计
8.3.6 文本域 (Textfield)
文本域是一个单行的文本输入设备, 通常用于获
取一行用户输入的字符, 如用户名, 密码的输入等 。
例如:
例 8.10 TextfieldDemo.java
import java.awt.*;
import java.awt.event.*;
public class TextfieldDemo extends Frame implements
ActionListener
{
第 8章 Java的 GUI设计
public static void main(String[] args)
{TextfieldDemo frame = new TextfieldDemo(); }
public TextfieldDemo()
{ setSize(300,100);
setLayout(new GridLayout(2,2));
Label l1 = new Label("User:");
TextField user = new TextField("");
user.addActionListener(this);
Label l2 = new Label("Password:");
TextField pass = new TextField("");
pass.addActionListener(this);
add(l1);
第 8章 Java的 GUI设计
add(user);
add(l2);
add(pass);
setVisible(true); }
public void actionPerformed(ActionEvent evt)
{ String arg = evt.getActionCommand();
System.out.println(""+arg); }
}
第 8章 Java的 GUI设计
因为只允许有一行文字,所以当按下 Enter或
Return键时,ActionListener可以通过 actionPerformed()
检测到这个事件。如果需要,还可以增加其他的组件
监听者。
除了注册一个 ActionListener,你还可以注册一个
TextListener来接收关于个别击键的通知。它的回调方
法是 textValueChanged(TextEvent)。程序运行结果如图
8.11所示。
第 8章 Java的 GUI设计
图 8.11
第 8章 Java的 GUI设计
8.3.7 文本区 (TextArea)
文本区是一个多行多列的文本输入设备 。 你可以
用 setEditable(boolean)将它设置成只读的 。 文本区将显
示水平和垂直的滚动条 。 下面这个范例创建了一个 4行
× 30字符的文本, 最初它含有 "Hello!"字符 。
例 8.11 TextAreaDemo.java
import java.awt.*;
import java.awt.event.*;
public class TextAreaDemo extends Frame implements
TextListener
第 8章 Java的 GUI设计
{
public static void main(String[] args)
{
TextAreaDemo frame = new TextAreaDemo();}
public TextAreaDemo()
{
setSize(300,100);
TextArea area = new TextArea("Hello!",4,30);
area.addTextListener(this);
add(area);
第 8章 Java的 GUI设计
setVisible(true);}
public void textValueChanged(TextEvent evt)
{ System.out.println(""+evt); }
}
用 addTexListener指定的监听者将以和文本域相同
的方式接收到关于击键的通知 。
可以给文本区增加一般的组件监听者, 然而, 由
于文本是多行的, 按下 Enter键将导致把另一个字符送
入缓冲 。 如果你需要识别, 输入的结束,, 你可以在
文本区旁放置一个, 应用, 或, 确认, 按钮, 以便用
户指明, 输入的结束, 。 程序运行结果如图 8.12所示 。
第 8章 Java的 GUI设计
图 8.12
第 8章 Java的 GUI设计
8.3.8 列表 (List)
一个列表可将各个文本选项显示在一个区域中,
这样就可以在同时看到若干个条目 。 列表可以滚动,
并支持单选和多选两种模式 。 例如:
例 8.12 ListDemo.java
import java.awt.*;
import java.awt.event.*;
public class ListDemo extends Frame
implements ItemListener
{ public static void main(String[] args)
第 8章 Java的 GUI设计
{ListDemo frame = new ListDemo(); }
public ListDemo()
{ setSize(100,200);
List list = new List(4,true);
list.add("First");
list.add("Second");
list.add("Third");
list.add("Fourth");
list.addItemListener(this);
add(list);
第 8章 Java的 GUI设计
setVisible(true);}
public void itemStateChanged(ItemEvent evt)
{ String state = "deselected";
if (evt.getStateChange() == ItemEvent.SELECTED)
state = "selected";
System.out.println(evt.getItem()+""+state); }
}
构造函数的数值参数定义了按可见列计算的列表
高度 。 这个值也可能被布局管理器覆盖 。 一个值为 true
的布尔型参数表明这个列表允许用户作多个选择 。
第 8章 Java的 GUI设计
选取或取消一个条目时, AWT将一个 ItemEvent的
实例送往列表 。 用户双击滚动列表中的一个条目时,
单选模式和多选模式的列表都会产生一个 ActionEvent,
根据每个平台的约定来决定列表中的条目是否被选取 。
对于 Unix/Motif环境, 单击会加亮列表中的一个条目,
只有双击才会触发列表事件 (选取条目 )。
程序运行结果如图 8.13所示 。
第 8章 Java的 GUI设计
图 8.13
第 8章 Java的 GUI设计
8.3.9 画布 (Canvas)
画布提供了一个空白 (背景色 )的空间 。 除非你用
setSize()显式地定义它的大小, 否则它的大小就是 0× 0。
画布的空间可以用来绘图, 显示文本, 接收键盘
或鼠标的输入 。 通常, 画布用来提供一个一般的绘图
空间或者为客户组件提供工作区域 。
画布可以, 监听, 所有适用于一个普通组件的事
件。特别地,你还可能想增加 KeyListener、
MouseMotionListener和 MouseListener对象,以允许以
某种方式对用户输入作出反应。
第 8章 Java的 GUI设计
注:如要在画布中接收键盘事件, 必须调用画布
的 requestFocus()方法 。 如果缺少这个步骤, 一般不能
将击键, 导向, 画布 。 而且键盘事件会送往另一个组
件, 或整个地丢失 。
下面是画布的一个范例 。 用户每击一次键, 这个程
序就改变一次画布的颜色 。
例 8.13 CanvasDemo.java
import java.awt.*;
import java.awt.event.*;
import java.util.*;
第 8章 Java的 GUI设计
public class CanvasDemo extends Canvas implements
KeyListener
{ int index;
Color colors[] = {Color.red,Color.green,Color.blue };
public static void main(String args[])
{ Frame f = new Frame("Canvas");
CanvasDemo mc = new CanvasDemo();
f.add(mc,BorderLayout.CENTER);
f.setSize(150,150);
第 8章 Java的 GUI设计
mc.requestFocus();
mc.addKeyListener(mc);
f.setVisible(true); }
public void paint(Graphics g)
{ g.setColor(colors[index]);
g.fillRect(0,0,getSize().width,getSize().height);}
第 8章 Java的 GUI设计
图 8.14
第 8章 Java的 GUI设计
public void keyTyped(KeyEvent ev)
{ index++;
if (index == colors.length) index =0;
repaint(); }
public void keyPressed(KeyEvent ev) { }
public void keyReleased(KeyEvent ev) { }
}
程序运行结果如图 8.14所示 。
第 8章 Java的 GUI设计
8.3.10 面板 (Panel)
像 Frame一样, Panel提供空间来连接任何 GUI组件,
包括其他面板 。 每个面板都可以有它自己的管理程序 。
一旦一个面板对象被创建, 为了能被看见, 必须将它
添加到窗口或框架对象上 。 用 Container类中的 add()方
式可以做到这一点 。
下面的程序创建了一个小的黄色面板,并将它加
到了一个框架对象上。
第 8章 Java的 GUI设计
例 8.14 FrameWithPanel.java
import java.awt.*;
public class FrameWithPanel extends Frame
{
public FrameWithPanel (String str)
{super (str);}
public static void main (String args[])
{ FrameWithPanel fr = new FrameWithPanel ("Frame with
Panel");
Panel pan = new Panel();
第 8章 Java的 GUI设计
fr.setSize(200,200);
fr.setBackground(Color.blue);
fr.setLayout(null);
pan.setSize (100,100);
pan.setBackground(Color.yellow);
fr.add(pan);
fr.setVisible(true);}
}
程序的运行结果如图 8.15所示 。
第 8章 Java的 GUI设计
图 8.15
第 8章 Java的 GUI设计
8.3.11 滚动面板 (ScrollPane)
滚动面板提供了一种不能作为自由窗口的通用容
器, 它总是和一个容器相关联 (例如框架 )。 滚动面板提
供了到一个更大的区域的视窗以及操纵这个视窗的滚
动条 。 例如:
例 8.15 ScrollPaneDemo.java
import java.awt.*;
import java.awt.event.*;
public class ScrollPaneDemo
{
第 8章 Java的 GUI设计
public static void main(String[] args)
{ Frame f = new Frame("ScrollPane");
Panel p = new Panel();
ScrollPane sp = new ScrollPane();
p.setLayout(new GridLayout(3,4));
for (int i = 0; i < 12; i++)
{p.add(new Button("Button"+i));}
sp.add(p);
f.add(sp,"Center");
f.setSize(150,150);
f.setVisible(true); }
}
第 8章 Java的 GUI设计
图 8.16
第 8章 Java的 GUI设计
程序运行结果如图 8.16所示 。
滚动面板创建和管理滚动条, 并持有一个组件 。
它不能控制自己所用的布局管理器, 但可以将一个面
板加入到滚动面板中, 配置面板的布局管理器, 并在
那个面板中放置你的组件 。
通常, 滚动面板上的事件均通过滚动面板所包含
的组件进行处理 。
第 8章 Java的 GUI设计
8.4 菜 单
菜单与其他组件有一个重要的不同:不能将菜单
添加到一般的容器中, 而且不能使用布局管理器对它
们进行布局, 只能将菜单加到一个菜单容器中 。 你可
以通过使用 setMenuBar()方法将菜单放到一个框架中,
从而启动一个菜单, 树, 之后, 便可以将菜单加到菜
单条中, 并将菜单或菜单项加到菜单中 。
弹出式菜单是一个例外, 因为它们可以以浮动窗
口形式出现, 因此不需要布局 。
第 8章 Java的 GUI设计
8.4.1 帮助菜单
菜单条的一个特性是你可以将其中一个菜单指定
为帮助菜单 。 这可以用 setHelpMenu(Menu) 来做到, 但
必须先加入到菜单条中, 它才会和本地平台的帮助菜
单以同样的方式被处理 。 对于 X/Motif类型的系统, 被
设定为帮助菜单的菜单条将显示在菜单条的最右边 。
第 8章 Java的 GUI设计
8.4.2 菜单条 (MenuBar)
一个菜单条组件是一个水平菜单 。 它只能加入到
一个框架中, 并成为所有菜单树的根 。 在一个时刻,
一个框架可以显示一个菜单条 。 然而, 你可以根据程
序的状态修改菜单条, 这样就可以在不同的时刻显示
不同的菜单 。 例如:
Frame f = new Frame("MenuBar");
MenuBar mb = new MenuBar();
f.setMenuBar(mb);
菜单条不支持监听者 。 作为普通菜单行为的一部
分, 在菜单条的区域中发生的预期事件会被自动处理 。
第 8章 Java的 GUI设计
8.4.3 菜单 (Menu)
菜单组件提供了一个基本的下拉式菜单 。 它可以
加入到一个菜单条或者另一个菜单中 。 例如:
MenuBar mb = new MenuBar();
Menu m1 = new Menu("File");
Menu m2 = new Menu("Edit");
Menu m3 = new Menu("Help");
mb.add(m1);
mb.add(m2);
第 8章 Java的 GUI设计
mb.setHelpMenu(m3);
f.setMenuBar(mb);
生成的菜单如图 8.17所示 。
第 8章 Java的 GUI设计
图 8.17
第 8章 Java的 GUI设计
8.4.4 菜单项 (MenuItem)
菜单项组件是菜单树的文本, 叶, 结点 。 它们通
常被加入到菜单中, 以构成一个完整的菜单 。 例如:
例 8.16 MenuBarDemo.java
import java.awt.*;
import java.awt.event.*;
public class MenuBarDemo extends
Frame implements ActionListener
{
public static void main(String[] args)
第 8章 Java的 GUI设计
{MenuBarDemo frame = new MenuBarDemo(); }
public MenuBarDemo()
{ setSize(200,200);
MenuBar mb = new MenuBar();
Menu m1 = new Menu("File");
MenuItem mi1 = new MenuItem("New");
mi1.addActionListener(this);
MenuItem mi2 = new MenuItem("Load");
mi2.addActionListener(this);
第 8章 Java的 GUI设计
MenuItem mi3 = new MenuItem("Save");
mi3.addActionListener(this);
MenuItem mi4 = new MenuItem("Quit");
mi4.addActionListener(this);
m1.add(mi1);
m1.add(mi2);
m1.add(mi3);
m1.add(mi4);
Menu m2 = new Menu("Edit");
Menu m3 = new Menu("Help");
第 8章 Java的 GUI设计
mb.add(m1);
mb.add(m2);
mb.add(m3);
setMenuBar(mb);
setVisible(true); }
public void actionPerformed(ActionEvent evt)
{ String arg = evt.getActionCommand();
System.out.println(arg); }
}
第 8章 Java的 GUI设计
通常, 将一个 ActionListener加入到一个菜单项对象
中, 以提供菜单的行为 。 程序的运行结果如图 8.18所示 。
第 8章 Java的 GUI设计
图 8.18
第 8章 Java的 GUI设计
8.4.5 复选菜单项 (CheckboxMenuItem)
复选菜单项是一个可操作的的菜单项, 可以在菜
单上有选项 (“开, 或, 关, )。 来看如下例子:
例 8.17 MenuBarDemo.java
import java.awt.*;
import java.awt.event.*;
public class MenuBarDemo extends
Frame implements ItemListener
{ public static void main(String[] args)
第 8章 Java的 GUI设计
{MenuBarDemo frame = new MenuBarDemo();}
public MenuBarDemo()
{ setSize(200,200);
MenuBar mb = new MenuBar();
Menu m1 = new Menu("File");
MenuItem mi1 = new MenuItem("Save");
CheckboxMenuItem mi2 = new
CheckboxMenuItem("Persistent");
mi2.addItemListener(this);
m1.add(mi1);
m1.add(mi2);
第 8章 Java的 GUI设计
Menu m2 = new Menu("Edit");
mb.add(m1);
mb.add(m2);
setMenuBar(mb);
setVisible(true); }
public void itemStateChanged(ItemEvent evt)
{ String state = "deselected";
if(evt.getStateChange()== ItemEvent.SELECTED)
第 8章 Java的 GUI设计
state = "selected";
System.out.println(evt.getItem()+" "+state); }
}
可以用 ItemListener接口来监视复选菜单。因此当
复选框状态发生改变时,就会调用 itemStateChanged()
方法。程序运行结果如图 8.19所示。
第 8章 Java的 GUI设计
图 8.19
第 8章 Java的 GUI设计
8.4.6 弹出式菜单 (PopupMenu)
弹出式菜单提供了一种独立的菜单, 它可以在任
何组件上显示 。 你可以将菜单条目和菜单加入到弹出
式菜单中去 。 例如:
例 8.18 PopupMenuDemo.java
import java.awt.*;
import java.awt.event.*;
第 8章 Java的 GUI设计
public class PopupMenuDemo extends Frame implements
ActionListener
{ Button b;
PopupMenu pm;
public static void main(String[] args)
{PopupMenuDemo frame = new PopupMenuDemo(); }
public PopupMenuDemo()
{ setSize(100,100);
第 8章 Java的 GUI设计
setLayout(new BorderLayout());
b = new Button("Popup");
b.addActionListener(this);
pm = new PopupMenu("Popup");
MenuItem s = new MenuItem("Save");
MenuItem l = new MenuItem("Load");
pm.add(s);
pm.add(l);
add(b,BorderLayout.CENTER);
add(pm);
第 8章 Java的 GUI设计
setVisible(true);}
public void actionPerformed(ActionEvent
evt){pm.show(b,10,10);}
}
为了显示弹出式菜单, 需要一个组件的引用, 作
为 x和 y坐标轴的起点 。 通常, 要使用组件的触发器来
激活弹出式菜单 。 在上面这个范例中, 触发器是 Button
b。 程序运行结果如图 8.20所示 。
注:弹出式菜单必须加入到一个“父”组件中,
这与将组件加入到容器中是不同的。在上面这个范例
中,弹出式菜单被加入到了周围的框架中。
第 8章 Java的 GUI设计
图 8.20
第 8章 Java的 GUI设计
8.5 布 局 管 理 器
8.5.1 Flow Layout
Flow布局管理器用于对组件逐行地定位, 每完成一
行, 一个新行便又开始 。 与其他布局管理器不一样的
是, Flow布局管理器不限制它所管理的组件的大小,
允许它们有自己的最佳大小 。
第 8章 Java的 GUI设计
Flow布局管理器允许将组件左对齐或右对齐 。 如
果想在组件之间创建一个更大的最小间隔, 可以规定
一个界限 。 当用户对由 Flow布局管理的区域进行缩放
时, 布局就发生变化, 如图 8.21所示 。
下面的例子就是如何用类容器的 setLayout()方法来
创建 Flow布局对象并安装它们的 。
setLayout(new FlowLayout(int align,int hgap,int vgap));
对齐的值必须是 FlowLayout.LEFT,
FlowLayout.RIGHT或 FlowLayout.CENTER。例如:
setLayout(new FlowLayout(FlowLayout.RIGHT,20,40));
第 8章 Java的 GUI设计
图 8.21
当用户改变窗口的大小时
第 8章 Java的 GUI设计
例 8.19构造并安装一个新的 Flow布局, 它带有规定
好的居中对齐方式和一个缺省的 5单位的水平和垂直间
隙 。 这个模块代码将几个按钮添加到框架中的一个
Flow布局中 。
例 8.19 FlowLayoutDemo.java
import java.awt.*;
public class FlowLayoutDemo
{ private Frame f;
private Button button1,button2,button3;
第 8章 Java的 GUI设计
public static void main (String args[])
{ FlowLayoutDemo mflow = new
FlowLayoutDemo();mflow.go();}
public void go()
{ f = new Frame ("Flow Layout");
f.setLayout(new FlowLayout());
button1 = new Button("Ok");
button2 = new Button("Open");
button3 = new Button("Close");
f.add(button1);
第 8章 Java的 GUI设计
f.add(button2);
f.add(button3);
f.setSize (100,100);
f.setVisible(true);}
}
运行结果如图 8.22所示 。
第 8章 Java的 GUI设计
图 8.22
第 8章 Java的 GUI设计
8.5.2 BorderLayout
Border布局管理器为在一个 Panel或 Window中放置
组件提供一个更复杂的方案 。 Border布局管理器包括
五个明显的区域:东, 南, 西, 北, 中 。
北占据面板的上方,东占据面板的右侧,等等。
中间区域是在东、南、西、北都填满后剩下的区域。
当窗口垂直延伸时,东、西、中区域延伸;而当窗口
水平延伸时,南、北、中区域延伸,如图 8.23所示。
Border布局管理器是用于 Dialog和 Frame的缺省布
局管理器。
第 8章 Java的 GUI设计
图 8.23
当用户改变窗口的大小时
第 8章 Java的 GUI设计
注:当窗口缩放时, 按钮相应的位置不变化, 但
其大小改变 。
可以用从 Container类继承的 setLayout()方法来将布
局设定为 Border布局 。 下面的代码表示出了 Border布局
管理器的特性 。
第 8章 Java的 GUI设计
例 8.20 BordLayoutDemo.java
import java.awt.*;
public class BordLayoutDemo
{ private Frame f;
private Button bn,bs,bw,be,bc;
public static void main(String args[])
{ BordLayoutDemo bord = new
BordLayoutDemo();bord.go(); }
public void go()
{ f = new Frame("Border Layout");
第 8章 Java的 GUI设计
bn = new Button("B1");
bs = new Button("B2");
be = new Button("B3");
bw = new Button("B4");
bc = new Button("B5");
f.add(bn,BorderLayout.NORTH);
第 8章 Java的 GUI设计
f.add(bs,BorderLayout.SOUTH);
f.add(be,BorderLayout.EAST);
f.add(bw,BorderLayout.WEST);
f.add(bc,BorderLayout.CENTER);
f.setSize (200,200);
f.setVisible(true); }
}
程序运行结果如图 8.24所示 。
第 8章 Java的 GUI设计
图 8.24
第 8章 Java的 GUI设计
setLayout(new BorderLayout())构造并安装一个新
Border布局, 在组件之间没有间隙 。
setLayout(new BorderLayout(int hgap,int vgap)构
造并安装一个 Border布局,在由 hgap和 vgap规定的组
件之间有规定的间隙。在布局管理器中,组件必须被
添加到指定的区域。区域名称拼写要正确,尤其是在
选择不使用常量 (如 add(button,"Center"))而使用
add(button,BorderLayout.CENTER)时,拼写与大写很
关键。
第 8章 Java的 GUI设计
可以使用 Border布局管理器来产生布局, 且带有在缩
放时在一个方向, 另一方向或双方向上都延伸的元素 。
可以仅将单个组件添加到 Border布局管理器五个区域
的每一个当中 。 如果添加不止一个, 只有最后一个看得
见 。 后面的示例将演示如何用中间容器来允许不止一个
组件被放在单个 Border布局管理器区域的空间里 。
注:布局管理器给予南, 北组件最佳高度, 并强迫
它们与容器一样宽, 但对于东, 西组件, 给予最佳宽度,
而高度受到限制 。
第 8章 Java的 GUI设计
8.5.3 GridLayout
Grid布局管理器为放置组件提供了灵活性。它先用
许多行和栏来创建管理程序,然后组件就填充到由管
理程序规定的单元中。比如,由语句 new
GridLayout(3,2)创建的有三行两栏的 Grid布局能产生如
图 8.25所示的六个单元。
第 8章 Java的 GUI设计
图 8.25
当用户改变窗口大小时
第 8章 Java的 GUI设计
Grid布局管理器总是忽略组件的最佳大小 。 所有
单元的宽度是相同的, 是根据单元数对可用宽度进行
平分而定的 。 同样地, 所有单元的高度也是相同的,
是根据行数对可用高度进行平分而定的 。
将组件添加到网格中的命令决定它们占有的单元 。
单元的行数是从左到右填充, 就像文本一样, 而页是
从上到下由行填充 。 下面是一个 GridLayout应用的示例 。
第 8章 Java的 GUI设计
例 8.21 GridLayoutDemo.java
import java.awt.*;
public class GridLayoutDemo
{ private Frame f;
private Button b1,b2,b3,b4,b5,b6;
public static void main(String args[])
{ GridLayoutDemo grid = new GridLayoutDemo();
grid.go(); }
第 8章 Java的 GUI设计
public void go()
{ f = new Frame("Grid example");
f.setLayout (new GridLayout (3,2));
b1 = new Button("1");
b2 = new Button("2");
b3 = new Button("3");
b4 = new Button("4");
b5 = new Button("5");
b6 = new Button("6");
f.add(b1);
f.add(b2);
第 8章 Java的 GUI设计
f.add(b3);
f.add(b4);
f.add(b5);
f.add(b6);
f.pack();
f.setVisible(true); }
}
运行结果如图 8.26所示 。
setLayout(new GridLayout())创建并安装一个 Grid布局,
每行中的每个组件有一个栏缺省 。
第 8章 Java的 GUI设计
setLayout(new GridLayout(int rows,int cols))创建并
安装一个带有规定好行数和栏数的 Grid布局 。 对布局
中所有组件所给的大小一样 。
setLayout(new GridLayout(int rows,int cols,int hgap,
int vgap)创建并安装一个带有规定好行数和栏数的网格
布局 。 布局中所有组件所给的大小一样 。 hgap和 vgap
规定组件间各自的间隙:水平间隙放在左右两边及栏
与栏之间;垂直间隙放在顶部, 底部及每行之间 。
第 8章 Java的 GUI设计
图 8.26
第 8章 Java的 GUI设计
8.5.4 GridBagLayout
最复杂的布局管理器是 GridBagLayout。
GridBagLayout与 GridLayout有点相似,它也是将组件
排在格子里,但是 GridBagLayout在网格的基础上提供
更复杂的布局。它允许单个组件在一个单元中不填满
整个单元,而只是占用最佳大小,也允许单个组件扩
展成不止一个单元,并且可以用任意顺序加入组件。
第 8章 Java的 GUI设计
为了使用 GridBagLayout,必须构造一个
GridBagConstraints对象。 GridBagConstraints用于指定
如何用 GridBagLayout放置组件。 GridBagConstraints对
象包含一些重要的参数,以指定组件的放置方式,这
些参数的含义如下:
● gridx,gridy,gridwidth和 gridheight参数 。 这四个
参数用于指定组件在网格中的位置 。 gridx和 gridy值用
于指定组件左上角的坐标; gridwidth和 gridheight决定
组件将占用多少行和列 。
第 8章 Java的 GUI设计
● 加权参数 weightx和 weighty。 GridBagLayout内的每
个区域都必须设置它的加权参数, 即 weightx和 weighty。
如果将权值设置为 0,那么这个区域就不会在那个方向
上扩张或收缩, 超出它的初始大小 。
● fill和 anchor参数。 fill参数用于指定组件在单元格内
进行伸缩时的填充方式,该参数可以有四种参数值:
GridBagConstraints.NONE(不伸缩 )、
GridBagConstraints.HORIZONTAL(水平伸缩 )、
GridBagConstraints.VERTICAL(垂直伸缩 )和
GridBagConstraints.
第 8章 Java的 GUI设计
BOTH(水平和垂直同时伸缩 )。 anchor参数用于指
定组件在一个单元格内靠在它的什么部位。可选
GridBagConstraints.CENTER(居中 )、
GridBagConstraints.NORTH(北 )、
GridBagConstraints.NORTHEAST(东北 )、
GridBagConstraints.EAST(东 )、
GridBagConstraints.SOUTHEAST(东南 )、
GridBagConstraints.SOUTH(南 )、
GridBagConstraints.SOUTHWEST(西南 )、
GridBagConstraints.WEST(西 )或者
GridBagConstraints.NORTHWEST(西北 )。
第 8章 Java的 GUI设计
● 填充参数 insets,ipadx和 ipady。 insets参数用于设置
沿单元格边界的外部填充空白区域 。 ipadx和 ipady则用
于指定在环绕组件四周的单元格内部填充空白区域 。
下面我们通过一个例子学习如何使用 GridBagLayout。
例 8.22 GridBagLayoutDemo.java
import java.awt.*;
public class GridBagLayoutDemo extends Frame
{ Canvas c;
Choice cb;
第 8章 Java的 GUI设计
TextArea ta;
TextField tf;
Button b1,b2,b3;
GridBagLayout gbLayout;
GridBagConstraints gbConstraints;
public static void main(String args[])
{GridBagLayoutDemo demo = new
GridBagLayoutDemo();}
public GridBagLayoutDemo()
{ gbLayout = new GridBagLayout();
第 8章 Java的 GUI设计
setLayout(gbLayout);
gbConstraints = new GridBagConstraints();
ta = new TextArea("TextArea",5,10);
cb = new Choice();
cb.addItem("Linden");
cb.addItem("Birch");
cb.addItem("Ceder");
tf = new TextField("TextField");
b1 = new Button("Button 1");
b2 = new Button("Button 2");
第 8章 Java的 GUI设计
b3 = new Button("Button 3");
c = new Canvas();
c.setBackground(Color.blue);
c.setSize(10,5);
// textarea
gbConstraints.weightx = 0;
gbConstraints.weighty = 0;
gbConstraints.fill = GridBagConstraints.BOTH;
addComponent(ta,gbLayout,gbConstraints,0,0,1,3);
第 8章 Java的 GUI设计
// button b1
gbConstraints.fill = GridBagConstraints.HORIZONTAL;
addComponent(b1,gbLayout,gbConstraints,0,1,2,1);
// choice button
addComponent(cb,gbLayout,gbConstraints,2,1,2,1);
// button b2
gbConstraints.weightx = 1000;
gbConstraints.weighty = 1;
gbConstraints.fill = GridBagConstraints.BOTH;
addComponent(b2,gbLayout,gbConstraints,1,1,1,1);
第 8章 Java的 GUI设计
// button b3
gbConstraints.weightx = 0;
gbConstraints.weighty = 0;
gbConstraints.fill = GridBagConstraints.BOTH;
addComponent(b3,gbLayout,gbConstraints,1,2,1,1);
// text field
addComponent(tf,gbLayout,gbConstraints,3,0,2,1);
// canvas
addComponent(c,gbLayout,gbConstraints,3,2,1,1);
setSize(250,150);
第 8章 Java的 GUI设计
setVisible(true);}
private void addComponent(Component c,GridBagLayout g,
GridBagConstraints gc,int row,int column,int width,
int height)
{ gc.gridx = column;
gc.gridy = row;
gc.gridwidth = width;
gc.gridheight = height;
g.setConstraints(c,gc);
add(c); }
} 程序运行结果如图 8.27所示 。
第 8章 Java的 GUI设计
图 8.27
第 8章 Java的 GUI设计
8.5.5 CardLayout
Card布局管理器能将界面看作一系列的卡, 其中
的一个在任何时候都可见 。 用 add()方法可将卡添加到
Card布局中 。 Card布局管理器的 show()方法响应请求转
换到一个新卡中 。 下例就是一个带有 5张卡的框架 。
例 8.23 CardLayoutDemo.java
import java.awt.*;
import java.awt.event.*;
public class CardLayoutDemo implements
MouseListener
第 8章 Java的 GUI设计
{ Panel p1,p2,p3,p4,p5;
Label l1,l2,l3,l4,l5;
CardLayout myCard;
Frame f;
public static void main (String args[])
{ CardLayoutDemo ct = new CardLayoutDemo();
ct.init(); }
public void init()
{ f = new Frame ("Card Test");
myCard = new CardLayout();
f.setLayout(myCard);
p1 = new Panel();
第 8章 Java的 GUI设计
p2 = new Panel();
p3 = new Panel();
p4 = new Panel();
p5 = new Panel();
l1 = new Label("This is the first Panel");
p1.setBackground(Color.yellow);
p1.add(l1); p1.addMouseListener(this);
l2 = new Label("This is the second Panel");
p2.setBackground(Color.green);
p2.add(l2); p2.addMouseListener(this);
l3 = new Label("This is the third Panel");
第 8章 Java的 GUI设计
p3.setBackground(Color.magenta);
p3.add(l3); p3.addMouseListener(this);
l4 = new Label("This is the fourth Panel");
p4.setBackground(Color.white);
p4.add(l4); p4.addMouseListener(this);
l5 = new Label("This is the fifth Panel");
p5.setBackground(Color.cyan);
p5.add(l5); p5.addMouseListener(this);
f.add(p1,"First");
第 8章 Java的 GUI设计
f.add(p2,"Second");
f.add(p3,"Third");
f.add(p4,"Fourth");
f.add(p5,"Fifth");
myCard.show(f,"First");
f.setSize (200,200);
f.setVisible(true); }
public void mouseClicked(MouseEvent e)
{myCard.next(f);}
public void mousePressed(MouseEvent e){}
第 8章 Java的 GUI设计
public void mouseReleased(MouseEvent e) {}
public void mouseEntered(MouseEvent e) {}
public void mouseExited(MouseEvent e) {}
}
程序运行结果如图 8.28所示 (鼠标点击左面板将视
图转换到右面板, 等等 )。
第 8章 Java的 GUI设计
图 8.28
第 8章 Java的 GUI设计
8.5.6 不使用布局管理器
除了以上介绍的各种布局管理器, Java也允许程序
员不使用布局管理器, 而是直接指定各个组件的位置 。
不使用布局管理器的例子如下:
例 8.24 NoLayoutDemo
import java.awt.*;
public class NoLayoutDemo
{ public static void main(String[] args)
{ Frame f = new Frame();
f.setLayout(null);
第 8章 Java的 GUI设计
Choice cb = new Choice();
cb.addItem("item 1");
cb.addItem("item 2");
cb.addItem("item 3");
Button b1 = new Button("Button 1");
Button b2 = new Button("Button 2");
Button b3 = new Button("Button 3");
f.add(cb); f.add(b1);
f.add(b2); f.add(b3);
b1.setBounds(25,25,60,26);
第 8章 Java的 GUI设计
b2.setBounds(100,40,90,22);
b3.setBounds(220,30,70,55);
cb.setBounds(50,80,70,18);
f.setSize(300,150);
f.setVisible(true); }}
第 8章 Java的 GUI设计
程序中用 setBounds()方法设置每个组件的位置和大
小 。 也许大家觉得这种方法才是我们常见的方式, 看
起来更简单和方便, 但是请注意, Java的目的是通用
于各种平台, 不使用布局管理器显然无法做到这一点 。
另外, 不使用布局管理器的界面, 在用于改变窗口大
小时是不会自动调整位置和大小的, 这显然不是一种
友好的界面设置方式 。 程序的运行结果如图 8.29所示 。
第 8章 Java的 GUI设计
图 8.29
第 8章 Java的 GUI设计
8.6 Java AWT事件处理机制
如果用户在用户界面层执行了一个动作 (鼠标点击
和按键 ),这将导致一个事件的发生 。 事件是描述发生
了什么的对象 。 存在各种不同类型的事件类用来描述
各种类型的用户交互 。 事件源是一个事件的产生者 。
例如, 在 Button组件上点击鼠标会产生以这个 Button 为
源的一个 ActionEvent。 这个 ActionEvent实例是一个对
象, 它包含关于刚才所发生的那个事件的信息的对象 。
事件处理器就是一个接收事件, 解释事件并处理用户
交互的方法 。
第 8章 Java的 GUI设计
8.6.1 事件的层次关系
从 JDK1.1开始, 事件接收和处理的方法发生了重
要的改变 。 JDK1.0采用的是层次事件模型, 而 JDK1.1
以上版本则采用的是委托事件模型 。
层次模型是基于容器的 。 事件先发送到组件, 然
后沿容器层次向上传播 。 没有被组件处理的事件会自
动地继续传播到组件的容器 。
第 8章 Java的 GUI设计
图 8.30
F r a m e
B u t t o n
P an e l
A c t i o n e v e n t
第 8章 Java的 GUI设计
例如, 图 8.30中, Button对象 (包含在一个 Frame上
的 Panel中 )上的鼠标点击首先向 Button发送一个动作事
件 。 如果它没有被 Button处理, 这个事件会被送往
Panel,如果它在那儿仍然没有被处理, 这个事件会被
送往 Frame。
这种模型有一个显著的优点:它简单, 而且非常
适合面向对象的编程环境 。 总的来说, 所有的组件都
继承了 java.awt.Component 类, 而 handleEvent() 就在
java.awt.Component类中 。 然而, 这种模型也存在缺点:
第 8章 Java的 GUI设计
(1) 事件只能由产生这个事件的组件或包含这个组
件的容器处理 。 这个限制违反了面向对象编程的一个
基本原则:功能应该包含在最合适的类中 。 而最适合
处理事件的类往往并不是源组件的容器层次中的成员 。
(2) 该模型中,大量的 CPU周期浪费在处理不相关
的事件上。任何对于程序来说不相关或者并不重要的
事件会沿容器层次一路传播,直到最后被抛弃。处理
的过程中不存在一种简单的方法来过滤事件。
第 8章 Java的 GUI设计
(3) 为了处理事件, 你必须定义接收这个事件的组
件的子类, 或者在基容器创建一个庞大的 handleEvent()
方法 。
委托事件模型是在 JDK1.1中引入的 。 在这个模型
中, 事件被送往产生这个事件的组件, 然而, 注册一
个或多个称为监听者的类取决于每一个组件, 这些类
包含事件处理器, 用来接收和处理这个事件 。 采用这
种方法, 事件处理器可以安排在与源组件分离的对象
中 。 监听者就是实现了 Listener接口的类 。
第 8章 Java的 GUI设计
事件是只向注册的监听者报告的对象 。 每个事件
都有一个对应的监听者接口, 规定哪些方法必须在适
合接收那种类型的事件的类中定义 。 实现了定义那些
方法的接口的类可以注册为一个监听者, 如图 8.31所示 。
第 8章 Java的 GUI设计
图 8.31
F r a m e
a c t i o n P e r f o r m e d ( A c t i o n E v e n t e ) {
…
}
A c t i o n h a n d l e rB u t t o n
P a n e l
P a n e l a n d F r a m e
e v e n t h a n d l e r s
A c t i o n e v e n t
第 8章 Java的 GUI设计
这种方法有以下优点:
(1) 事件不会被意外地处理 。 在层次模型中, 一个
事件可能传播到容器, 并在非预期的层次被处理 。
(2) 有可能创建并使用适配器 (adapter)类对事件动
作进行分类 。
(3) 委托模型有利于把工作分布到各个类中 。
(4) 新的事件模型提供对 JavaBeans的支持 。
这种方法也有一个缺点:尽管当前的 JDK支持委托
模型和 JDK1.0事件模型,但不能混合使用 JDK1.0和
JDK1.1。
第 8章 Java的 GUI设计
8.6.2 事件类型
我们已经介绍了在单一类型事件上, 下文中从组
件接收事件的通用机制 。 许多事件类在 java.awt.event包
中, 也有一些事件类在 API的其他地方 。 图 8.32显示了
事件的类层次关系 。
对于每类事件,都有一个接口,这个接口必须由
想接收这个事件的类的对象实现。这个接口还要求定
义一个或多个方法,当发生特定的事件时,就会调用
这些方法。表 8.4列出了这些 (事件 )类型,并给出了每
个类型对应的接口名称,以及所要求定义的方法。这
些方法的名称是易于记忆的,名称表示了会引起这个
方法被调用的源或条件。
第 8章 Java的 GUI设计
图 8.32
j a v a, u t i l,E v e n t O b j e c t
j a v a, a w t, A W T E v e n t
j a v a, b e a n s, b e a n C o n t e x t
A c t i o n E v e n t
A d j u s t m e n t E v e n t
C o m p o n e n t E v e n t
I t e m E v e n t
T e x t E v e n t
C o n t a i n e r E v e n t
F o c u s E v e n t
I n p u t E v e n t
W i n d o w E v e n t
K e y E v e n t
Mo u s e E v e n t
B e a n C o n t e x t E v e n t
.,.
第 8章 Java的 GUI设计
表 8.4 方法类型和接口
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)
第 8章 Java的 GUI设计
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)
第 8章 Java的 GUI设计
Window WindowListener
windowClosing(WindowEvent)
windowOpened(WindowEvent)
windowIconified(WindowEvent)
WindowDeiconified(WindowEvent)
WindowClosed(WindowEvent)
WindowActivated(WindowEvent)
WindowDeactivated(WindowEvent)
Container ContainerListener
componentAdded(ContainerEvent)
ComponentRemoved(ContainerEvent)
Text TextListener TextValueChanged(TextEvent)
第 8章 Java的 GUI设计
8.6.3 事件处理过程
本节将通过一个范例说明事件的处理过程 。 它将跟
踪鼠标被按下时, 鼠标的移动情况 (鼠标拖动 ),还将监
测当鼠标没有按下时, 鼠标的移动情况 (鼠标移动 )。
当鼠标按下或没有按下时,移动鼠标产生的事件
会被实现了 MouseMotionListener接口的类的对象检取。
这个接口要求定义两个方法,mouseDragged()和
mouseMoved()。即使你只对鼠标拖动感兴趣,也必须
提供这两个方法,但是 mouseMoved()的体可以是空的。
第 8章 Java的 GUI设计
要检取其他鼠标事件,包括鼠标点击,必须定义
MouseListener接口。这个接口包括若干个事件,即
mouseEntered,mouseExited,mousePressed、
mouseReleased和 mouseClicked。
发生鼠标或键盘事件时, 有关鼠标的位置和所按
下的键的信息可以从事件中得到, 代码如下 。
第 8章 Java的 GUI设计
例 8.25 ListenDemo.java
import java.awt.*;
import java.awt.event.*;
public class ListenDemo
implements MouseMotionListener,MouseListener
{ private Frame f;
private TextField tf;
第 8章 Java的 GUI设计
public static void main(String args[])
{ ListenDemo two = new ListenDemo(); two.go(); }
public void go()
{ f = new Frame("Two listeners example");
f.add (new Label("Click and drag the
mouse"),BorderLayout.NORTH);
tf = new TextField(30);
f.add (tf,BorderLayout.SOUTH);
f.addMouseMotionListener(this);
f.addMouseListener (this);
f.setSize(300,200);
第 8章 Java的 GUI设计
f.setVisible(true); }
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";
第 8章 Java的 GUI设计
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) {}
}
运行以上程序可看到如图 8.33所示界面 。 当在窗口
中拖动鼠标时, 底端的 TextField中将显示鼠标的当前
位置 。
第 8章 Java的 GUI设计
图 8.33
第 8章 Java的 GUI设计
● 定义多了多个接口
这个类由代码:
implements MouseMotionListener,MouseListener
声明 。 声明多个接口时, 可以用逗号隔开 。
第 8章 Java的 GUI设计
● 监听多个源
如果调用方法:
f.addMouseListener(this);
f.addMouseMotionListener(this);
则两种类型的事件都会引起 ListenDemo类中的方
法被调用 。 一个对象可以, 监听, 任意数量的事件源;
它的类只需要实现所要求的接口 。
第 8章 Java的 GUI设计
8.6.4 事件 Adapters(适配器 )
一旦指定一个类实现了某个事件监听器接口, 就
必须实现这个监听器接口的所有方法, 否则你只能将
你的类定义为抽象类而无法定义这个类的实例 。 从上
面的例子我们可以看到, 实现每个 Listener接口的所有
方法的工作量均是非常大的, 尤其是 MouseListener接
口和 ComponentListener接口 。
以 MouseListener接口为例,它定义了如下方法:
第 8章 Java的 GUI设计
① mouseClicked(MouseEvent)
② mouseEntered(MouseEvent)
③ mouseExited(MouseEvent)
④ mousePressed(MouseEvent)
⑤ mouseReleased(MouseEvent)
为了方便起见,Java语言提供了 Adapters类,用来
实现含有多个方法的类。这些 Adapters类中的方法是空
的。你可以继承 Adapters类,而且只需重写你所需要的
方法。
第 8章 Java的 GUI设计
public class MouseClickHandler extends MouseAdapter
{ // We just need the mouseClick handler,so we use
// the Adapter to avoid having to write all the
// event handler methods
public void mouseClicked(MouseEvent e)
{ // Do something with the mouse click..,}
}
第 8章 Java的 GUI设计
8.7 Swing 基 础
从 JDK1.2开始, AWT添加了被称为 Swing的新 GUI
库 。 Swing是基于 AWT基本结构创建的二级用户界面
工具集, Swing提供了一整套 GUI组件 。 为了保证可移
植性, 它是完全用 Java语言编写的 。
第 8章 Java的 GUI设计
8.7.1 Swing的层次结构
与 AWT比较, Swing提供了更完整的组件, 引入了
许多新的特性和能力 。 Swing API是围绕着实现 AWT各
个部分的 API构筑的 。 这保证了所有早期的 AWT组件
仍然可以使用 。 AWT采用了与特定平台相关的实现,
而绝大多数 Swing组件却不是这样做的, 因此, Swing
的外观和感觉是可客户化和可插的 。
第 8章 Java的 GUI设计
图 8.34显示了 JFC各个部分之间的相互关系 。
Java2D,Accessibility,Drag & Drop和 Accessibility API
是 AWT和 JFC的一部分, 但它们不属于 Swing。 这是因
为, 这些组件使用了一些本地代码, 而 Swing却不是这
样的 。
Swing是围绕着一个称为 JComponent的新组件构建
的, 而 JComponent则由 AWT的容器类扩展而来 。
图 8.35说明了 Swing组件的层次结构。
第 8章 Java的 GUI设计
图 8.34
第 8章 Java的 GUI设计
图 8.35
j a v a,a w t,C o n t a i n e r
c o m, s u n, j a v a, s w i n g, J C o m p o n e n t
J T e x t C o m p o n e n t
A b s t r a c t B u t t o n
J P a n e l
J C o m b o B o x
J L a b e l
J L a y e r e d P a n e
J L i s t
J T o o l B a r
J M e n u B a r
J P o p u p Me n u
J P a n e
J S c r o l l B a r
J S c r o l l P a n e
J S l i d e r
J T a b l e
J S e p a r a t o r
J T r e e
J P r o g r e s s B a r
J R o o t P a n e
J S p l i t P a n e
J T a b b e d P a n e
J T e x t F i e l d
H t m l E d i t o r K i t
J T e x t A r e a
J B u t t o n
J M e n u I t e m
J T o g g l e B u t t o n
J C h e c k B o x M e n u I t e m
J M e n u
J R a d i o B u t t o n M e n u I t e m
J R a d i o B u t t o n
J C h e c k B o x
J P a s s w o r d F i e l d
第 8章 Java的 GUI设计
8.7.2 Swing组件
Swing组件主要为文本处理, 按钮, 标签, 列表,
面板, 组合框, 滚动条, 滚动面板, 菜单, 表格和树
提供了组件 。 其中的一些组件如图 8.36所示 。
第 8章 Java的 GUI设计
图 8.36
JApplet JButton
第 8章 Java的 GUI设计
图 8.36
JComboBo JOptionPane
第 8章 Java的 GUI设计
图 8.36
JList JLabel
第 8章 Java的 GUI设计
JScrollPane JTable
图 8.36
第 8章 Java的 GUI设计
图 8.36
JScrollBar JSlider
第 8章 Java的 GUI设计
图 8.36
JToolti Jtree
第 8章 Java的 GUI设计
由于这些 Swing组件的功能和用法和 AWT组件基本
相似, 所以这里不再详细说明, 大家使用时可以参考
Sun公司提供的 JDK API文档 。
Swing都是作为 JComponent的子类来实现的, 它从
JComponent继承了如下功能:
● 边框:你可以用 setBorder()方法来指定在组件周围
显示的边框 。 还可用一个 EmptyBorder的实例来指定一
个组件在其周围留有一定的额外空间 。
第 8章 Java的 GUI设计
● 双缓冲:双缓冲可以改善一个频繁被改变的组件的
外观 。 现在, 你不需要编写双缓冲代码, 因为 Swing已
为你提供了 。 缺省情况下, Swing组件是双缓冲的 。
● 提示框:通过用 setToolTipText()方法来指定一个字
符串, 你可以提供给用户有关某个组件的帮助信息 。
当光标暂停在组件上时, 所指定的字符串就会在组件
附近的一个小窗口中显示出来 。
第 8章 Java的 GUI设计
● 键盘导航:使用 registerKeyboardAction()方法, 你可
以让用户以键盘代替鼠标来操作 GUI。 用户为启动一
个动作所必须按下的修饰键与字符的组合, 由一个
KeyStroke对象来表示 。
第 8章 Java的 GUI设计
● 应用程序范围的可插式外观和感觉:每个 Java应用
程序在运行时刻有一个 GUIManager对象,它用于确定
运行时刻 Swing组件的外观和感觉。由于安全性的限制,
你可以通过调用 UIManager.setLookAndFeel()方法选择
所有 Swing组件的外观和感觉。在你所看见的东西背后,
每个 JComponent对象都有一个对应的 ComponentGUI对
象,它用来执行所有关于该 JComponent的绘制、事件
处理、大小判定等任务。
第 8章 Java的 GUI设计
8.7.3 建立 Swing窗口
Swing程序用 JFrame 对象实现了它们的窗口 。
JFrame类是 AWT Frame类的一个子类 。 它还加入了一
些 Swing所独有的特性 。 例如:
例 8.26 SwingDemo.java
import java.awt.*;
import javax.swing.*;
public class SwingDemo extends JFrame
{
第 8章 Java的 GUI设计
public static void main(String[] args)
{ SwingDemo frame = new SwingDemo();
frame.setSize(300,100);
frame.setVisible(true); }
第 8章 Java的 GUI设计
public SwingDemo()
{ Container pane = getContentPane();
JPanel p = new JPanel();
p.setLayout(new FlowLayout());
JScrollPane sp = new JScrollPane(p);
JButton b1 = new JButton("Button 1");
JButton b2 = new JButton("Button 2");
p.add(b1);
第 8章 Java的 GUI设计
p.add(b2);
JTextField tf = new JTextField("Hello!",10);
p.add(tf);
JCheckBox one = new JCheckBox("One",true);
JCheckBox two = new JCheckBox("Two",false);
JCheckBox three = new JCheckBox("Three",true);
p.add(one);
第 8章 Java的 GUI设计
p.add(two);
p.add(three);
pane.add(sp); }
}
第 8章 Java的 GUI设计
这段代码与使用 Frame的代码十分相似, Swing的
各种组件用法也和 AWT的对应组件基本相同, 只是功
能更为强大, 组件也更多样 (因为 Swing组件的用法和
前面介绍的 AWT组件基本相同, 这里不再一一举例,
大家可以参考前面的例子, 参看 Java的 API文档自己学
习使用 )。 惟一的区别在于, 你不能将组件加入到
JFrame中, 只能将组件加入到 JFrame的 content pane中,
或者提供一个新的 content pane。
第 8章 Java的 GUI设计
一个 content pane是一个包含除菜单条 (如果有的话 )
外所有框架的可视组件的容器。要获得一个 JFrame的
content pane,可使用 getContentPane()方法。要设置它
的 content pane(如前面例所示 )可使用 setContentPane()方
法。程序的运行结果如图 8.37所示。
第 8章 Java的 GUI设计
图 8.37