当前位置: 首页 > >

第7章 Java的图形用户界面

发布时间:

第7章

Java的图形用户界面

在本章中,我们将会学到:
GUI组件的构造和使用

7.1 3 7.2 3 7.3 3 7.4 3

布局管理器 Swing组件介绍

事件处理

7.1 GUI组件
7.1.1抽象窗口工具包(AWT:Abstract Window Toolkit) 抽象窗口工具包(Abstract Window Toolkit)简称:AWT,是为Java程序提供图形用户界面(Graphics User Interface :GUI)的一组API。主要功能包括:用户界面组件、界面布局设计和管理、图形图像处理、 事件处理等。 下面是AWT包中部分重要类和子包: 1)java.awt.Component :抽象类,是AWT包所有组件类的超类; 2)java.awt.datatransfer :提供数据传输和剪贴板功能的包 3)java.awt.dnd :提供用户拖曳操作功能的包 4)java.awt.event :提供事件处理功能的包 5)java.awt.image :提供图像处理功能的包 6)java.awt.peer :提供AWT程序运行所需界面的同位体运行 7)javax.swing :Swing组件包 组件是构成GUI的基本元素,Component类是AWT包所有组件类的超类,它为其它子类提供了很多组件设计功 能,如:位置、大小、字体、颜色、同位体等。“同位体”(peer)是个比较难理解的概念,简单来讲, 同位体是对窗体界面系统的抽象。当程序员调用AWT对象时,调用被转发到该对象所对应的一个Peer 上,再由Peer调用本地对象方法,完成对象的显示。

图7-1表达了一个AWT的Frame组件是如何通过同位体显示出来的。
并且,从同位体的使用机制来看,AWT包组件的显示要受到本*教ǖ挠跋欤虼讼衷诖蠖嗍褂 Swing包来代替AWT包。除AWT包之外,Swing包也提供了GUI设计功能,它们都是Java基本类库 (JFC:Java Foundation Class)的一部分,不过Swing提供了比AWT包更强大的功能,且具备完全 跨*台的能力,Swing包将在后面章节介绍。AWT作为最基本的组件包,掌握了它有助于学*其它组 件功能,因此还是有详细介绍的必要。

图7-2是Windows*台中的部分AWT组件。 图7-3描述了AWT包中组件类的层次关系。

图7-1 AWT组件的同位体调用机制 AWTCom ponent PeerComp onent

系 统 * 台 显 示 系统

Frame

PeerFrame

图7-2 AWT组件外观
TextField Choice List

Label
Checkbox

Checkbox

TextArea

Button

图7-3 AWT包中组件类的层次
MenuComponent

MenuBar
MenuItem Scrollbar Menu

Object

Button
Canvas Container Panel ScrollPanel Window Applet Frame Dialog

Component

Checkbox Choice

Label
TextComponent

TextField

TextArea List
符号表示: 组件 容器

7.1.2 GUI组件与容器
表7-1 Component组件类的常用方法
常用方法 addXXXListener(XXXListener l) setBackground(Color c) getBackground() setForeground(Color c) 功能 添加指定的XXX监听器,接收此组件发出的事件 设置组件的背景色 获得组件的背景色 设置组件的前景色

getForeground()
setFont(Font f)

获得组件的前景色
设置组件的字体

getFont()
getSize()

获得组件的字体
返回组件的大小

getWidth()
getHeight() getX() getY() paint(Graphics g) repaint() requestFocus() setBounds(int x, int y, int width, int height) setEnabled(boolean b) setVisible(boolean b) toString() update(Graphics g)

返回组件的当前宽度
返回组件的当前高度 返回组件原点的当前 x 坐标 返回组件原点的当前 y 坐标 绘制此组件 重绘此组件 请求此组件获得输入焦点,并且此组件的顶层组件成为获得焦点的 Window 移动组件并调整其大小 根据参数 b 的值启用或禁用此组件 根据参数 b 的值显示或隐藏此组件 返回此组件及其值的字符串表示形式 更新组件

一、AWT容器组件
1、窗体(框架)(Frame) Frame类是Window类的子类,它具备边框,标题栏,系统菜单, 最大、最小化按钮,是一个具备完全功能的窗体。 它的构造方法如下: ? Frame(); 默认构造方法,创建没有标题的窗体 ? Frame(String title);创建以title为标题栏文字的窗体其主要成 员方法如下: ? setSize(int width,int height);为窗体设置大小,width为窗体 宽度,height为高度 ? pack();以紧凑组件的方式设置窗体大小 ? setTitle(String title);为窗体设置标题 ? setVisible(boolean b);为窗体设置可见性,默认时窗体为不 可见。

例7-1:创建简单窗体 例7-2:创建简单窗体另一种形式

例7-1:创建简单窗体
import java.awt.*; public class FrameDemo extends Frame { public FrameDemo(String title) //自定义构造方法,title为窗体标题 { super(title); //调用超类的带参数 的构造方法 this.setSize(200,100); setVisible(true); } public static void main(String[] args) { new FrameDemo("简单窗体"); } } 【运行结果】 (显示一个简单的窗口,如图所示。)

例7-2:创建简单窗体另一种形式
import java.awt.*; public class FrameDemo extends Frame { Frame f=new Frame(); Label la1=new Label("您好,这是Label组件!"); public FrameDemo() { f.add(la1); f.setTitle("简单窗体"); f.pack(); f.setVisible(true); } public static void main(String[] args) { new FrameDemo(); } } 【运行结果】 (同样显示一个简单的窗口,内部包含一个标签组件,如图所示。)

2、对话框(Dialog)
对话框是可以接受用户输入的弹出式窗体,它也是一种带边框的容器,与Frame不 同的是对话框依赖于其它的窗体,当窗体最小化时,对话框也会随之最小化。 对话框可分为模态对话框(model)和非模态对话框(modelless),其中 模态对话框只能响应对话框范围内的事件,对话框外部的事件则不能响应; 而非模态对话框则不受这个限制。所以模态对话框通常用于注册窗口或“另 存为”窗口等必须等用户首先响应的情况。Dialog的常用构造方法如下: Dialog(Frame frm);创建一个不可见、无标题的非模式的对话框,相关联的窗体是 框架类的对象frm。 ? Dialog(Frame frm, String title, boolean modal);创建一个不可见、以title 内容为标题的对话框,相关联的窗体是框架类的对象frm,第二个参数为true 表示创建模式对话框,为false表示创建非模式对话框。 ? Dialog的方法继承自Component和Window,所以它具备Component和 Window类的所有特征,如setVisible()方法等,其它重要方法如下: ? boolean isModal( );返回对话框的类型,模式对话框返回true,否则,返回 false。 ? void setModal(boolean b);设置对话框的类型,参数true表示设置模式对 话框,为false表示设置非模式对话框。

例7-3:创建模态对话框

例7-3:创建模态对话框
import java.awt.*; public class MyFrame extends Frame { Button btnOpen=new Button(“打开”); MyFrame(String s) { super(s); // 调用父类构造方法 add(btnOpen);// 将按钮对象添加到窗体中 setSize(200,150); setVisible(true); // 设置窗体是可见的 } public static void main(String args[]) { MyFrame f=new MyFrame(“窗口”); // 创建窗体,标题为“窗口” MyDialog dlg=new MyDialog(f,“登录对话框”,true);// 创建对话框 } } class MyDialog extends Dialog //对话框类 { MyDialog(Frame f,String s,boolean b) // 构造方法,f是与对话框相关的窗体 { super(f,s,b); // 调用父类的构造方法,对话框将依赖于f窗体 setSize(120,50); setVisible(true); // 设置对话框可见 } } 【运行结果】 (如图所示:登录对话框再窗体的前方,在未关闭对话框的前提下不能操作窗体,即“打开”按钮无法使用)

3、面板(Panel)
面板是一种容器,与Window类的子类不同的是:面板 (及其子类)无边框、无标题,不能被移动、放大、 缩小或关闭。因此,面板不能作为独立的容器使用, 通常它作为中间容器,用以容纳其它组件,或子面 板。通常面板被放置在其他能独立使用的容器中, 如放置在窗体内。 Panel类的构造方法如下: ? Panel( );创建一个使用默认的布局管理器的面板。 ? Panel(LayoutManager layout);创建一个使用指 定布局管理器的面板。

例7-4:面板的使用

例7-4:面板的使用
import java.awt.*; public class MyFrame extends Frame { Button btnOpen=new Button("打开"); Button btnClose=new Button("关闭"); Panel p=new Panel(); MyFrame(String s) { super(s); // 调用父类构造方法 p.setBackground(Color.CYAN); //将面板p背景色设为青色 add(p); //把面板p添加到窗口中 p.add(btnOpen); // 将按钮添加到面板中 p.add(btnClose); setSize(200,100); setVisible(true); } public static void main(String args[]) { MyFrame f=new MyFrame("窗口"); //创建框架(窗口),标题为"窗口“ } } 【运行结果】 (如图所示:窗体包含一个青色面板,此面板中包含两个按钮)

二、AWT基本组件
1、按钮(Button) Button的构造方法: Button(String label); 常用成员方法: setLabel(String label); 将按钮的标签文字设置为指定的字符串 getLabel(); 获得此按钮的标签文字。 setActionCommand(); 设置此按钮激发的操作事件的命令名称。(默认即按钮的标签文字); getActionCommand(); 得到此按钮激发的操作事件的命令名称。 2、标签(Label) Label的构造方法: Label(String label); 常用成员方法: setText(); 设置此标签的文本。 getText(); 获取此标签的文本。 3、文本框(TextField) TextField的构造方法: TextField (String label); 常用成员方法: setText(String str); 将此文本框显示的文本设置为指定文本(继承自父类TextComponent)。 getText(); 获取文本框的文本(继承自父类TextComponent)。 setEditable(boolean b); 设置判断此文本框是否可编辑的标志。 setEchoChar(char c); 设置此文本框的回显字符(继承自父类TextComponent)。

二、AWT基本组件
4、文本区(TextArea) TextArea的构造方法: TextArea(String label); 构造一个新文本区,该文本区具有指定的文本。 TextArea(String text,int rows,int columns); 构造一个新文本区,该文本区具有指定的文本,以及 指定的行数和列数。(注意:列columns并不总是等于字符的个数,它是*似*均字符宽度, 与*台有关) 常用成员方法: setText(String str); (与文本框的功能相同) getText();(与文本框的功能相同) setEditable(boolean b); (与文本框的功能相同) append(String str); 将给定文本追加到文本区的当前文本。 insert(String str,int pos); 在此文本区的指定位置插入指定文本。 5、单选框与复选框(Checkbox) Checkbox的构造方法: Checkbox(String label); Checkbox(String label,boolean state,CheckboxGroup group); 使用指定的标签文字构造一个 Checkbox,使用布尔值state将它设置为指定的默认选择状态,并使它处于指定的复选框组中 (用于将多个复选框指定为一组单选框)。 常用成员方法: getLabel(); 获得此复选框的标签。 setState(boolean state); 设置复选框的“开”、“关”状态。 getState(); 返回此复选框的“开”、“关”状态。

二、AWT基本组件
6、列表框(List)与下拉选择框(Choice) List的构造方法: List(int rows,boolean multipleMode);创建一个初始化显示为指定行数rows的新滚动列表,如果multipleMode的值 为 true,则可从列表中同时选择多项。 Choice的构造方法: Choice(); (选择框只有这一种构造形式) 常用成员方法: add(); 将一个项目添加到此 List或Choice中,替代已经过时的addItem()。 getItem(int index);获得此List或Choice中指定索引上的字符串。 getItemCount();返回此List或Choice中项目的数量。 getSelectedIndex();返回当前选定项的索引,如果没有选定任何内容,则返回 -1。 getSelectedItem();获得当前选择项目的字符串表示形式。 insert(String item,int index); 将项目item插入到的指定位置index上。 remove(int position); 从指定位置position上移除一个项目。 7、菜单组件 菜单(Menu)应包含菜单项(MenuItem),并被包含在菜单栏(MenuBar)中,它们的位置关系如图7-3。 菜单组件的构造方法: 菜单项(MenuItem): MenuItem(String label);构造具有指定标签的新菜单项。 MenuItem(String label, MenuShortcut s);创建具有关联的键盘快捷方式的菜单项。 菜单(Menu):Menu(String label);构造具有指定标签的新菜单。 菜单栏(MenuBar):MenuBar(); 创建新的菜单栏。

例7-5:构建菜单示例

图7-3 菜单类及其子类的位置关系

Menu

MenuBar

Menu

MenuItem

MenuItem

例7-5:构建菜单示例
import java.awt.*; public class ShortcutMenu extends Frame { MenuShortcut msOpen=new MenuShortcut('O'); MenuShortcut msSave=new MenuShortcut('S'); MenuShortcut msExit=new MenuShortcut('X'); MenuBar menubar=new MenuBar(); Menu mnFile=new Menu("文件"); Menu mnHelp=new Menu("帮助"); Menu mnNew=new Menu("新建"); //“新 建”是嵌套菜单 MenuItem miOpen=new MenuItem("打开",msOpen); MenuItem miSave=new MenuItem("保存",msSave); MenuItem miExit=new MenuItem("退出",msExit); MenuItem miAbout=new MenuItem("关于"); MenuItem miC=new MenuItem(“C/C++文档”); MenuItem miJava=new MenuItem("Java文档"); public ShortcutMenu(String title) { super(title); mnNew.add(miC); mnNew.add(miJava); mnFile.add(mnNew);//将嵌套菜单mnNew加入到菜单 mnFile上 mnFile.add(miOpen); mnFile.add(miSave); mnFile.addSeparator(); mnFile.add(miExit); mnHelp.add(miAbout); menubar.add(mnFile); menubar.setHelpMenu(mnHelp); this.setMenuBar(menubar); this.setSize(200,150); this.setVisible(true); } public static void main(String[] args) { new ShortcutMenu("菜单的快捷键示例"); } } 【运行结果】 (如图所示:按下Ctrl+X键时,会退出窗体)

7.2 布局管理器(LayoutManager)
7.2.1 什么是布局管理器
布局(Layout)就是指组件在容器中分布情况。布局管理器(LayoutManager),是 Java中用来管理组件的排列、位置、大小等分布属性的类,Java通过对容器设置 相应的布局来实现不同的外观。

7.2.2 为什么要使用布局管理器 通常的编程语言,在控制GUI显示时使用的是自身系统的坐标,例如VB的标准 坐标系统的原点在界面的左上角,X轴为水*方向,Y轴为垂直方向,如 图7-4所示。

X轴

Y 轴

(x,y)

一般的Windows编程语言在设置界面布局时,组件的位置会严格按照这个坐标系统(X, Y)来定位,这称为“绝对坐标定位”。一个GUI界面在Widnows*台中可以正常 显示,但是移植到其它*台时将会导致混乱,这也是一般编程语言不具备跨*台能 力的一个重要原因。 Java处理GUI界面的方法是:将容器界面按照一定规则划分为若干网格,然后根据网格中 各单元格的位置及其相应布局规则放入指定组件。这种根据单元格位置定位组件的 方法称为“相对坐标定位”,因为这种方法与坐标(X,Y)无关,所以解决了跨 *台时的GUI界面显示问题。

7.2.3 常用的布局管理器
常用的布局管理器主要有:FlowLayout(流水式布局)、BorderLayout(边 界式布局)、GridLayout(网格式布局)、CardLayout(卡片式布局)、 GridBagLayout(网格袋式布局)。 一、FlowLayout(流水式布局) 1. 布局特点: ? FlowLayout把组件按照从左到右,从上到下的顺序逐次排列,组件排满 容器的一行,会自动切换到下一行继续排列; ? 是Panel类及其子类(如:Applet)的默认布局。 2. 构造方法: ? FlowLayout(); 构造一个新的 FlowLayout,组件居中对齐,默认水*和 垂直间距是5个像素。 ? FlowLayout(int align); 构造一个新的 FlowLayout,对齐方式由align指 定。 ? FlowLayout(int align, int hgap, int vgap); 创建一个新的FlowLayout, 具有指定的对齐方式align以及指定的水*间隙hgap和垂直间隙vgap。 注意:对齐参数align的值必须是下列值FlowLayout.LEFT、 FlowLayout.RIGHT、FlowLayout.CENTER、FlowLayout.LEADING 或 FlowLayout.TRAILING中之一,它们都是public static final int 型的静 态整型常量,其相对应的整型值如表7-2: 3.流水式布局实例:

例7-6:流水式布局的作用

表7-2 FlowLayout对齐参数字符串表示及其对应常量值表

java.awt.FlowLayout
align参数字符串表示 对应常量值

LEFT 0 CENTER 1 RIGHT 2
LEADING 3 TRAILING 4

例7-6:流水式布局的作用
import java.awt.*; public class FlowLayoutDemo extends Frame { Button b1=new Button("Button1"); Button b2=new Button("Button2"); Button b3=new Button("Button3"); Button b4=new Button("Button4"); Button b5=new Button("Button5"); public FlowLayoutDemo(String title) { super(title); this.setLayout(new FlowLayout()); //更改布局为流水式布局 this.add(b1); //向容器中添加组件 this.add(b2); this.add(b3); this.add(b4); this.add(b5); this.setSize(300,100); this.setVisible(true); } public static void main(String[] args) { new FlowLayoutDemo("FlowLayouDemo example!"); } } 【运行结果】 (如图所示:窗体包含5个按钮,默认时组件从左到右放置,并居中排列,组件排满窗口的一行,自动切换到下一行继续 排列,各组件之间的间隔为5个像素)

二、BorderLayout(边界式布局)
1. 布局特点: ? BorderLayout按照位置将容器划分为5个区域: “North”、“South”、“West”、“East”、 “Center”;分别代表:“上”、“下”、“左”、 “右”、“中” 5个位置; ? 是Window类及其子类(如:Frame、Dialog)的默认 布局。 2. 构造方法: ? BorderLayout();构造一个的新边界布局,组件之间没 有间距。 ? BorderLayout(int hgap, int vgap);构造一个边界布 局,并指定的组件之间的水*和垂直间距。 3.边界式布局实例:

例7-7:边界式布局的作用

例7-7:边界式布局的作用
import java.awt.*; public class BorderLayoutDemo extends Frame { Button btnNorth=new Button("North"); Button btnSouth=new Button("South"); Button btnWest=new Button("West"); Button btnEast=new Button("East"); Button btnCenter=new Button("Center"); public BorderLayoutDemo(String title) { super(title); this.add(btnNorth,"North"); this.add(btnSouth,"South"); this.add(btnWest,"West"); this.add(btnEast,"East"); this.add(btnCenter,"Center"); this.setSize(200,150); this.setVisible(true); } public static void main(String[] args) { new BorderLayoutDemo("BorderLayout示例!"); } } 【运行结果】 (如图所示:窗体包含5个按钮,组件按照add()方法指定的约束参数“North”、“South”、“West”、“East”、 “Center”放置放置在相应的位置,组件之间没有间隔)

三、GridLayout(网格式布局)
1、布局特点: GridLayout将容器分隔成若干行列规则的网格,网格中 各单元格大小完全一致,组件添加时按照“从左至右、 先行后列”的方式排列,即组件先添加到网格的第一行 的最左边的单元格,然后依次向右排列,如果排满一行 就自动切换到下一行继续排列; 2、构造方法: ? GridLayout() ;创建具有默认值的网格布局,即每个组 件占据一行一列。 ? GridLayout(int rows, int cols) ;创建具有指定行数和 列数的网格布局。 ? GridLayout(int rows, int cols, int hgap, int vgap) ; 创建具有指定行数和列数的网格布局,并指定组件行列 间隔 3、网格式布局实例:

例7-8:网格式布局的作用

例7-8:网格式布局的作用
import java.awt.*; public class GridLayoutDemo extends Frame { Button[] btn=new Button[10]; Panel p=new Panel(); public GridLayoutDemo(String title) { super(title); p.setLayout(new GridLayout(3,4,5,5)); for(int i=0;i<10;i++) { btn[i]=new Button(Integer.toString(i));p.add(btn[i]); } this.add(p); this.setSize(200,130); this.setVisible(true); } public static void main(String[] args) { new GridLayoutDemo("GridLayout示例"); } } 【运行结果】 (如图所示:窗体包含10个按钮,组件行列之间有5个单位的间隔)

四、CardLayout(卡片式布局)
1、布局特点: CardLayout将容器中的每个组件看作一张卡片。一次只能 看到一张卡片,而容器充当卡片的堆栈。第一个添加到 CardLayout容器中的对象组件为可见组件。 CardLayout提供了一组方法来浏览容器中的卡片。 2、构造方法: ? CardLayout();创建一个组件间隔大小为 0 的新卡片 布局。 ? CardLayout(int hgap, int vgap);创建一个组件之间 具有指定的水*和垂直间隔的新卡片布局。 3、卡片式布局实例:

例7-9:设计一个包含两个面板(卡片)的卡 片式布局,面板可以循环切换显示

例7-9:设计一个包含两个面板(卡片)的卡片式布局,面板可以循 环切换显示
import java.awt.*; import java.awt.event.*; //导入了事件处理类包 //本例需要实现事件处理功能,因此本窗口实现了ActionListener接口 public class CardLayoutDemo extends Frame implements ActionListener { Panel p1,p2,p_card,p_btn; Button btnPrev,btnNext; CardLayout card; public CardLayoutDemo(String title) { super(title); this.setLayout(new FlowLayout());//将本窗体改为流水布局 p1=new Panel(); p2=new Panel(); p_card=new Panel(); p_btn=new Panel(); btnPrev=new Button("前一页"); btnNext=new Button("后一页"); card=new CardLayout(); p_card.setLayout(card);//将面板p_card设为卡片布局 p_btn.add(btnPrev);p_btn.add(btnNext); p1.add(new Label("锦瑟无端五十弦,一弦一柱思华年。庄生晓梦迷蝴蝶,望帝春心托杜鹃。")); p2.add(new Label("沧海月明珠有泪,蓝田日暖玉生烟。此情可待成追忆,只是当时已悯然。")); p_card.add("Previous",p1);//将面板p1添加到卡片布局面板p_card中 p_card.add("Next",p2); //将面板p2添加到卡片布局面板p_card中 this.add(p_card); this.add(p_btn); p_card.add(p1,"Previous");//将面板p1添加到卡片布局面板p_card中 p_card.add(p2,"Next"); //将面板p2添加到卡片布局面板p_card中 this.setSize(430,120); this.setVisible(true); } public void actionPerformed(ActionEvent e)//实现ActionListener接口中的方法 { if(e.getSource()==btnPrev)//判断是否触发了btnPrev按钮 { card.previous(p_card);//卡片容器p_card切换到前一张} if(e.getSource()==btnNext)//判断是否触发了btnNext按钮 { card.next(p_card);//卡片容器p_card切换到下一张 } } public static void main(String[] args) { new CardLayoutDemo("CardLayout示例"); } } 【运行结果】 (如图所示:单击窗体中的2个按钮,上面的诗句会循环切换)

五、GridBagLayout(网格袋式布局)
1、布局特点: GridBagLayout可以实现前面所有的布局效果,当然它的构造形 式也相当复杂,它需要先创建一个约束对象来确定各组件的布局约 束形式,然后再按照约束布置组件。 2、构造方法: GridBagLayout();创建网格袋布局管理器的唯一形式。 GridBagConstraints();创建网格袋约束的唯一形式。 为网格袋布局面板pane添加一个按钮button的大致构造步骤如下: ? GridBagLayout gridbag = new GridBagLayout(); ? GridBagConstraints c = new GridBagConstraints(); ? pane.setLayout(gridbag); ? c.fill = GridBagConstraints.BOTH; //以下为网格袋约束对 象设置约束属性 ? c.weightx = 1.0; ? …… ? gridbag.setConstraints(button, c); ? pane.add(button);

7.2.4

容器嵌套

例7-10:调查卡程序 import java.awt.*; public class AwtComponent extends Frame { Label labTip1=new Label("姓名:"); Label labTip2=new Label("学历:"); Label labTip3=new Label("年龄:"); Label labTip4=new Label("性别:"); Label labTip5=new Label("爱好:"); Label labTip6=new Label("自我介 绍:"); TextField txtName=new TextField(10); Choice choGrade=new Choice(); List listAge=new List(3); Checkbox ckbBacketball=new Checkbox("篮球"); Checkbox ckbBandmon=new Checkbox("羽毛球"); Checkbox ckbPingpang=new Checkbox(“乒乓球”); CheckboxGroup ckg=new CheckboxGroup(); Checkbox ckbMale=new Checkbox("男",ckg,true); Checkbox ckbFemale=new Checkbox("女",ckg,false); TextArea taReduce=new TextArea(3,20); Button btnSubmit=new Button("提交"); Button btnReset=new Button("重写"); Panel p1=new Panel(); Panel p2=new Panel(); Panel p3=new Panel(); public AwtComponent(String title) { super(title); choGrade.add("专科"); choGrade.add("本科"); choGrade.add(“硕士”);listAge.add("18"); listAge.add("19"); listAge.add("20"); listAge.add("21"); p1.add(labTip1); p1.add(txtName); p1.add(labTip2); p1.add(choGrade); p1.add(labTip3); p1.add(listAge); p2.add(labTip4); p2.add(ckbMale); p2.add(ckbFemale); p2.add(labTip5); p2.add(ckbBacketball); p2.add(ckbBandmon); p2.add(ckbPingpang); p3.add(labTip6); p3.add(taReduce);p3.add(btnSubmit); p3.add(btnReset);this.add(p1,"North"); this.add(p2,"Center"); this.add(p3,"South"); this.pack(); this.setVisible(true); } public static void main(String[] args) { new AwtComponent("调查卡程序"); } } 【运行结果】 (如图7-2所示因为界面复杂,使用单一容器无法组织布局,而网格袋布局使用太复杂,因此采用容器嵌套)

7.2.5

空布局(null)

例7-11:空布局示例 import java.awt.*; public class NullLayoutDemo extends Frame { Label lab1=new Label("姓名:");Label lab2=new Label("性别:");Label lab3=new Label("年龄:");Label lab4=new Label("成绩:"); TextField t1=new TextField(); TextField t2=new TextField(); TextField t3=new TextField(); TextField t4=new TextField(); Button b1=new Button(“查询”); Button b2=new Button(“更改”); Button b3=new Button(“删除”); Button b4=new Button(“退出”); int x=0,y=0,w=0,h=0; int s_x=0,s_y=0; NullLayoutDemo(String title) { super(title); setLayout(null);//设置空布局 this.setSize(300,177);//注意:在此设置窗体大小 this.setVisible(true);//注意:在此设置窗体显示 Insets insets=this.getInsets();//获得窗体的Insets实例 w=this.getSize().width;//获得窗体的宽度 h=this.getSize().height;//获得窗体的高度 x=(w-insets.left-insets.right)/4;//x值为窗体容器空间的四分之一 y=(h-insets.top-insets.bottom)/5;//y值为窗体容器空间的五分之一 s_x=insets.left;//获得窗体左侧的Insets值 s_y=insets.top; //获得窗体顶侧的Insets值 //以下按顺序向窗体添加组件 add(lab1);add(t1); add(lab2);add(t2); add(lab3);add(t3); add(lab4);add(t4); add(b1);add(b2);add(b3);add(b4); //逐个设置组件的位置和大小 lab1.setBounds(0+s_x,0+s_y,x,y); t1.setBounds(x+s_x,0+s_y,3*x,y); lab2.setBounds(0+s_x,y+s_y,x,y); t2.setBounds(x+s_x,y+s_y,3*x,y); lab3.setBounds(0+s_x,2*y+s_y,x,y);t3.setBounds(x+s_x,2*y+s_y,3*x,y); lab4.setBounds(0+s_x,3*y+s_y,x,y);t4.setBounds(x+s_x,3*y+s_y,3*x,y); b1.setBounds(0+s_x,4*y+s_y,x,y); b2.setBounds(x+s_x,4*y+s_y,x,y); b3.setBounds(2*x+s_x,4*y+s_y,x,y); b4.setBounds(3*x+s_x,4*y+s_y,x,y); } public static void main(String[] args) { new NullLayoutDemo("空布局示例"); } } 【运行结果】 (如图所示,注意:文本框占行宽的四分之三)

7.3

Swing组件

7.3.1 Swing组件概述 Swing组件最早引入自JDK1.2,它们大部分是AWT组件的子组件,是由100%纯代码 编写的,不依赖与本*教ǖ亩缘忍澹╬eer)运行,具备完全跨*台的能 力,因此我们也把Swing组件称为“轻组件”,而AWT组件则称为“重组 件”。同AWT组件一样,Swing组件也是JFC(Java基本类库:Java Foundation Class)的一部分。Swing组件继承了AWT组件的特点,在一些 功能有所增强(如剪贴板、树形目录,动态按钮等),并且可以自由设置 和改变界面的整体风格(pluggable look and feel,PL&F)。在我们下载 的JDK工具包的demo目录中有Swing组件实例的完美演示!Swing组件以“J” 开头,大多数都来自于javax.swing包,只有JTableHeader和 JTextComponent不在swing包中(它们分别在swing.table和swing.text子 包中),因此在使用一般Swing组件的时候需要在程序中写入:import javax.swing.*;

Swing组件的类层次图如图7-6所示。
从上图可以看出,同AWT容器组件一样,Swing容器也分为“顶级容器”和“中间 容器”。“顶级容器”如JFrame、JDialog,“中间容器”主要指JPanel。 因为Java不允许直接将组件添加在Swing“顶级容器”中,因此需要在 Swing“顶级容器”中先创建一个“中间容器”,然后将组件添加到“中间 容器”。

图7-6
JComponent

Swing组件类层次结构图
AbstractButton
JToggleButton

JCheckBox
JRadioButton

Object Component Container

JLabel JList JComboBox
JMenuBar JOptionPane

JMenuItem JButton

JMenu

JPanel JScrollBar JText
Window

Frame
Dialog

JFrame JDialog

7.3.2 Swing组件实例
例7-12:简单Swing组件风格示例 import java.awt.*; import javax.swing.*; public class SwingDemo extends JFrame { public SwingDemo(String title) { super(title); JTextField t1=new JTextField(20); JButton b1=new JButton("Login"); Container pane=this.getContentPane(); pane.add(t1,"Center"); pane.add(b1,"South"); pack(); setVisible(true); } public static void main(String[] args) { try { //UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); //UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch(Exception e){} new SwingDemo("Swing简单示例"); } } 【运行结果】 (如左图所示。当打开代码第21行注释时,运行结果如右图所示)

7.3.3 MVC(Model-View-Controller)模型
MVC是面向对象设计中经典模型之一,该模型把程序的实现用三个部分组 成,简单说就是:它可以实现哪些状态(模型)、它的外观是什么 样子(视图)、它由什么来控制实现(控制器)。例如,我们鼠标 点击树形目录的节点,树形目录的子目录分支会自动展开或收缩。 树形目录的外观变化是存储在模型类库中,我们在窗口上看到的外 观是它的视图,当鼠标点击时,事件传递给控制器程序,由它负责 调用模型的数据,来完成视图的改变。过程如图7-7所示。 JFC UI
用户动作
Controller 处理用户交互

选择视图

View

用户请求
状态改变

外观显示

业务请求

状态数据 图7-7

Model

状态查询 MVC模型

借助于MVC模型,有助于减少代码重复、降低维护难度,在Web开发应用中, 也大量借用了此模型,并此模型基础上扩展出许多新的更强有力功 能的开发模型。

7.4 事件处理(Event Handle)概述
如果想要实现用户与组件的交互,就必须使用事件处理。 例如,我们用鼠标点击按钮,希望界面会得到一定的 反应。在这个过程中,用户在按钮上单击鼠标,按钮 组件接收鼠标动作并对用户的动作做出响应,触发组 件的鼠标单击事件,事件在对象间的传递是则是以消 息(Message)进行传输。相比VB这样的编程语言来 说,Java的事件处理在功能上要更底层,因此语法上 可能显得“繁琐”一些。

7.4.1 Java基于委托的事件处理模型
Java在事件处理的过程中,是围绕着一个称为“监听器” (Listener)的对象来进行的, 事件的接收、判断和处理都是委托“监听器”来全权完成, 这称为“基于委托的事件处理模 型”(Delegation Event Model)。 Java的事件处理过程是这样的:程序中使用“监听器” 对想要接收事件的组件进行监视, 当用户动作触发事件时,“监听器”会接收到它所监听组件 上的事件,然后根据事件类型, 自行决定该使用什么方法来处理。在整个事件处理过程中, “监听器”都是关键的核心。

Hot Tip
事件处理及相关概念大致有:事件、事件接口、监听器、注册(添 加)监听器、事件 类、事件接口中的方法、事件类的方法。 事件是组件对用户的动作的响应。而响应用户动作并产生事件的组 件就是事件源。如果 组件有监听器监听,组件产生的事件就会以消息的形式传递给监听器。 监听器根据监听到的 事件类型,调用相应的方法去执行用户的需求。而事件类和事件类的方 法的应用则在事件接 口方法中体现。 第9章示例9-9就是一个事件处理的例子,如果现在还对以上这些概 念感到模糊,我们再 看一个简单的事件处理的例子,通过这个示例来了解一下事件处理的相 关概念。 这个示例包含一个按钮和一个文本框,当单击按钮时,文本框显示“大 家好!”。 例10-1:简单的事件处理示例

Hot Tip
行号

EventHandle.java程序代码 import java.awt.*; import java.awt.event.*; //导入事件处理类所在的类包 //类EventHandle实现了事件监听器接口 public class EventHandle extends Frame implements ActionListener { TextField t1=new TextField(20); Button b1=new Button("登录"); public EventHandle(String title) { super(title); this.setLayout(new FlowLayout()); this.add(t1); this.add(b1); b1.addActionListener(this); //为按钮b1注册监听器this this.setSize(200,90); this.setVisible(true); } public void actionPerformed(ActionEvent e) //实现接口里的方法 { if(e.getSource()==b1) //判断事件源是否是按钮b1 { t1.setText("大家好!"); } } public static void main(String[] args) { new EventHandle("事件处理简单示例"); } }

Hot Tip
【运行结果】 (显示如图所示的窗口,当单击“登录”按钮时,文本框显示字符串“大家好!”。)

【代码说明】
通过这个示例,我们理清一下事件处理的全过程,与事件处理的相关步骤在程序清单中已 经标记出来,分别是代码第2、3、13、17、19行; 因此事件处理的步骤可以总结如下: 代码第2行,导入事件处理类所在的类包event包,ActionListener接口和ActionEvent类都 在这个包中。因为导入java.awt.*;并不会导入awt包下面的event子包的内容,所以此句是 必须的; 代码第3行,实现了ActionListener接口,这个接口包含一个actionPerformed (ActionEvent e)方法,因此在代码第17行重写了这个方法, actionPerformed方法可以处理动作事件(Acti onEvent); 代码第13行,为了让按钮b1能响应用户的动作,为b1注册了监听器this; 代码第17行,重写的方法actionPerformed (ActionEvent e)格式必须是public(公有的)、 void(无返回值),它有一个ActionEvent类型的参数,用以接收动作事件的信息,并存放在 对象e中; 代码第19行,ActionEvent类型的对象e调用getSource(),会获得事件源对象,借此判断用户 触发的是否是按钮b1,用户希望程序实现的功能代码应写在此方法内;

图画出了Java基于委托的事件处理模型流程。

图 Java基于委托的事件处理机制

下面我们把例10-1涉及的相关概念再对比列出,,参照图7-1彻底掌握这些概念

Hot Tip
概念 事件监听器接口 事件源 监听器 注册监听器 ActionListener b1 this addActionListener(this); 相应代码段

监听器接口中的方法
事件类 事件类的方法

actionPerformed()
ActionEvent getSource()
表 事件相关概念对照

1) 既然“监听器”是如此重要,那么什么样的对象有资格做“监听器”呢?; 从Java事件处理流程上看,用户对组件的动作在组件(事件源)上会产生事件,事件由监听 器接收,并分析事件类型,然后根据事件类型,将事件转交指定的接口方法处理。因此做为 监听器的对象必须了解事件监听接口的内容,也就是说“监听器”对象的类需要实现指定的 事件监听接口。 本例中的监听器this是类EventHandle的实例,类EventHandle实现了事件监听接口ActionLi stener,因此this可以做为监视Action事件的监听器使用。 2) 一个监听器可以监听多个事件源,一个事件源也可以注册多个监听器(当然有时无此必要 )。注册监听器时使用addXXXlistener()方法,删除时则使用removeXXXlistener()方法(例 如删除动作事件监听器可以使用removeActionlistener方法);

7.4.3 Java的事件处理类
Java的事件一般包括两种类型:用户事件和系统事件。 ? 用户事件:由用户动作引发的事件。例如,用户操作鼠标,按下键盘键等; ? 系统事件:由操作系统发出的事件。例如,窗口状态变化时自动刷新窗口内容等。 这里我们只探讨用户事件。 AWT组件事件都是由java.awt.AWTEvent类派生得到,它也是EventObject类的子类。AWT事 件共有12种类型,如图7-2所示

图 AWT包的事件处理类层次

7.4.4Java的事件及其监听器接口
AWT事件类共有10类,相应监听器接口共有11个。它们的对应关系及功能如表7-2。
事件类别 ActionEvent 功能描述 动作事件 接口名 ActionListener 接口中方法
actionPerformed(ActionEvnet e)

TextEvent
AdjustementEvent ItemEvent FocusEvent ContainerEvent ComponentEvent

文本事件
调整事件 项目事件 焦点事件 容器事件 组件事件

TextListener
AdjustmentListener ItemListener FocusListener ContainerListener ComponentListener

textValueChanged(TextEvent e)
adjustmentValueChanged(AdjustmentEvent e) itemStateChanged(ItemEvent e) focusGained(FocusEvent e) focusLost(FocusEvent e) componentAdded(ContainerEvent e) componentRemoved(ContainerEvent e) componentHidden(ComponentEvent e) componentMoved(ComponentEvent e) componentResized(ComponentEvent e) componentShown(ComponentEvent e) windowActived(WindowEvent e) windowClosed(WindowEvent e) windowClosing(WindowEvent e) windowDectivated(WindowEvent e) windowDeiconified(WindowEvent e) windowIconfied(WindowEvent e) windowOpened(WindwEvent e) mouseClicked(MouseEvent e) mouseEntered(MouseEvent e) mouseExited(MouseEvent e) mousePressed(MouseEvent e) mouseReleased(MouseEvent e)

WindowEvent

窗口事件

WindowListener

MouseEvent

鼠标事件

MouseListener

鼠标移动事件
KeyEvent 键盘事件

MouseMotionListener
KeyListener

mouseDragged(MouseMotionEvent e) mouseMoved(MouseMotionEvent e)
keyPressed(KeyEvent e) keyReleased(KeyEvent e) keyTyped(KeyEvent e)

Hot Tip
事件类的方法:包括从父类AWTEvent类中继承的方法和事件类本身特有的方法。 ? 从java.awt.AWTEvent类中继承的方法主要有:getSource(),getID(),toString(); 事件类特有的方法:根据组件特点及其事件类功能不同,方法有所不同,如ActionEvent类具有 getActionCommand()方法,AdjustementEvent类具有getValue(),getAdjustmentType()方法等; 部分事件类的常用方法功能简要描述如表7
事件类 ActionEvent TextEvent AdjustmentEvent ItemEvent 可产生事件的组件 Button,List,MenuItem,T extField等 TextArea,TextField Scrollbar List,Choice,Checkbox,C heckboxMenuItem 大部分组件 事件类的方法 getActionCommand() paramString() getValue() getAdjustmentType() getItem() getStateChange() getClickCount() getPoint() getX() getY() 方法功能描述 返回与此动作相关的命令字符串。 返回标识此文本事件的参数字符 串。 返回调整事件中的当前值。 返回导致值更改的调整类型。 返回受事件影响的项。 返回状态更改的类型(选中或取 消)。 返回鼠标单击次数。 返回鼠标事件相对于源组件的 x 、y 位置。 返回鼠标事件相对于源组件的水 * x 坐标。 返回鼠标事件相对于源组件的垂 直 y 坐标。 返回与按键相关联的字符。 返回与按键相关联的键整数值。

MouseEvent

KeyEvent

大部分组件

getKeyChar() getKeyCode()

Hot Tip
事件类的静态整形成员属性: 每种事件类都有一些从父类AWTEvent类中继承下来的 或是本身特有的静态整形成员属性,主要是一些描述 当前组件的状态的值,如KeyEvent.VK_LEFT属性代表 键盘“左箭头键”。部分成员属性会在后面的“事件 处理示例”一节中提及。由于篇幅原因,本书不作详 细描述,请读者自行参考JDK API Document。

7.5.1 动作事件与项目事件
动作事件(ActionEvent)是由用户动作造成组件的动作(比如按下按钮)产生的,(注意:要使用键盘在 Button组件上触发ActionEvent,需使用空格键)。项目事件(ItemEvent)是由用户在具备项目选择能 力的组件(比如列表框,选择框等)上触发。 例10-2:ActionEvent与ItemEvent示例 (要求:从列表框中选择项目,单击按钮时,选中的项目显示在文本框中) 其中ActionEvent由ActionListener接口的actionPerformed()方法处理;ItemEvent由ItemListener接口的 itemStateChanged()方法处理。

【运行结果】 (显示如图1所示的窗口,当选择列表框中的爱好时,文本框显示你选择的爱好的个数。)

(当单击“显示”按钮时,显示如图2所示的窗口,文本框显示你选择的爱好。)

【代码说明】 1)本类实现了两个接口ActionListener,ItemListener,分别用以处理按钮和文本框 产生的事件,如代码第4行。代码第28、41行分别重写了这两个接口的方法 actionPerformed()和itemStateChanged(); 2)代码第7行,使用了List(4,true);构造列表框,true参数代表此列表框可以多选; 3)代码第28行,重写方法actionPerformed()。代码第32行,列表框实例list调用 getSelectedItems()方法获得所有在列表框中选择的项目,将它们存储在字 符串数组str中。代码第35、36行,将数组的内容添加连接到字符串str_show; 4)代码第41行,重写方法itemStateChanged()。代码第43、48行,判断列表框中是 否有项目被选择(或取消选择),如果有项目被选择,e.getStateChange() 值返回为1,如果取消选择,e.getStateChange()值返回为2,静态常量表示 分别为ItemEvent. SELECTED和ItemEvent.DESELECTED;

7.5.2 文本事件
文本组件(如TextField,TextArea)在文本内容发生改变时(如键入,删除字符时),会产生TextEvent 类型事件。 处理TextEvent的接口是TextListener,接口中的方法textValueChanged(TextEvent e)
行号 1 2 3 4

TextEventDemo.java程序代码 import java.awt.*; import java.awt.event.*; import java.util.StringTokenizer;//StringTokenizer类在util包中 public class TextEventDemo extends Frame implements TextListener { TextField t1=new TextField(30); Label lab=new Label(""); String str=""; StringTokenizer st; public TextEventDemo(String title) { super(title); this.add(t1,"North"); this.add(lab,"South"); t1.addTextListener(this);//为文本框t1注册文本监听器 this.pack();//紧凑窗口 this.setVisible(true); } public void textValueChanged(TextEvent e) { if(e.getSource()==t1)//判断是否在文本框上产生了文本事件 { str=t1.getText(); st=new StringTokenizer(str," '.?");//以空格、单引号、句号、问号做为分隔符分析str字符串有多少字符串子段 int num=st.countTokens();//计算句子中单词的个数 lab.setText("现在单词个数:"+num+"个"); this.add(lab,"South"); } } public static void main(String[] args) { new TextEventDemo("实时单词计算"); } }

5
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21

运行结果】 (显示如图所示的窗口,当在文本框中输入句子时,标签中会显示句子中单词的个数。)

【代码说明】 类实现了接口TextListener,用以文本变化产生的事件,因此代码第19行,重写了接口的方法 textValueChanged()。代码第15行,为文本框t1注册了监听器; 代码第21行,判断事件源t1是否被触发;代码第24行,以空格、单引号、句号、问号做为分隔符创建 StringTokenizer类实例st,并分析str字符串有多少字符串子段;代码第26行,实例st调用 countTokens()方法获得子段(单词)的个数,StringTokenizer类的详细使用请参考第7章。

7.5.4 鼠标事件
当鼠标按下、释放、进入、离开组件,或在组件上方移过、拖曳时都会发生鼠标事件。鼠标 事件大致分为两类:普通鼠标事件(鼠标按下、释放、进入、离开)和鼠标拖动事件 (鼠标移过、拖曳)。分别由两个接口处理,其中MouseListener接口处理普通鼠标事件 (接口中包含5个方法),MouseMotionListener接口处理鼠标拖动事件(接口中包含2个 方法),参考表7-2。 例10-6: MouseListener接口示例 (要求:可以记录窗口上鼠标按下、释放、进入、离开和单、双击的位置)

行号 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16

MoveButton.java程序代码 import java.awt.*; import java.awt.event.*; public class MouseListenerDemo extends Frame implements MouseListener { Label message=new Label("这里显示鼠标动作"); public MouseListenerDemo(String title) { super(title); this.add(message,"North"); this.addMouseListener(this); this.setSize(200,150); this.setVisible(true); } public void mousePressed(MouseEvent e){//重写接口的方法 message.setText("鼠标被按下,位置在:"+e.getX()+","+e.getY()); } public void mouseReleased(MouseEvent e){ message.setText("鼠标被释放,位置在:"+e.getX()+","+e.getY()); } public void mouseEntered(MouseEvent e){ message.setText("鼠标已进入,位置在:"+e.getX()+","+e.getY()); } public void mouseExited(MouseEvent e){ message.setText("鼠标已退出,位置在:"+e.getX()+","+e.getY()); } public void mouseClicked(MouseEvent e){ if(e.getClickCount()==1){ //判断鼠标击键的次数是否为单击 message.setText("鼠标单击,位置在:"+e.getX()+","+e.getY()); } if(e.getClickCount()==2){ //判断鼠标击键的次数是否为双击 message.setText("鼠标双击,位置在:"+e.getX()+","+e.getY()); } } public static void main(String[] args) { new MouseListenerDemo("鼠标MouseListener接口示例"); } }

17
18 19

7.4.3 Java的事件处理类
运行结果】 (显示如图所示的窗口,当在文本框中输入句子时,标签中会显示句子中单词的个数。)

【代码说明】 类实现了接口TextListener,用以文本变化产生的事件,因此代码第19行,重写了接口的方法 textValueChanged()。代码第15行,为文本框t1注册了监听器; 代码第21行,判断事件源t1是否被触发;代码第24行,以空格、单引号、句号、问号做为分隔符创建 StringTokenizer类实例st,并分析str字符串有多少字符串子段;代码第26行,实例st调用 countTokens()方法获得子段(单词)的个数,StringTokenizer类的详细使用请参考第7章。

7.4.3 Java的事件处理类
运行结果】 (显示如图所示的窗口,当在文本框中输入句子时,标签中会显示句子中单词的个数。)

【代码说明】 类实现了接口TextListener,用以文本变化产生的事件,因此代码第19行,重写了接口的方法 textValueChanged()。代码第15行,为文本框t1注册了监听器; 代码第21行,判断事件源t1是否被触发;代码第24行,以空格、单引号、句号、问号做为分隔符创建 StringTokenizer类实例st,并分析str字符串有多少字符串子段;代码第26行,实例st调用 countTokens()方法获得子段(单词)的个数,StringTokenizer类的详细使用请参考第7章。

7.4.3 Java的事件处理类
运行结果】 (显示如图所示的窗口,当在文本框中输入句子时,标签中会显示句子中单词的个数。)

【代码说明】 类实现了接口TextListener,用以文本变化产生的事件,因此代码第19行,重写了接口的方法 textValueChanged()。代码第15行,为文本框t1注册了监听器; 代码第21行,判断事件源t1是否被触发;代码第24行,以空格、单引号、句号、问号做为分隔符创建 StringTokenizer类实例st,并分析str字符串有多少字符串子段;代码第26行,实例st调用 countTokens()方法获得子段(单词)的个数,StringTokenizer类的详细使用请参考第7章。

7.4.3 Java的事件处理类
运行结果】 (显示如图所示的窗口,当在文本框中输入句子时,标签中会显示句子中单词的个数。)

【代码说明】 类实现了接口TextListener,用以文本变化产生的事件,因此代码第19行,重写了接口的方法 textValueChanged()。代码第15行,为文本框t1注册了监听器; 代码第21行,判断事件源t1是否被触发;代码第24行,以空格、单引号、句号、问号做为分隔符创建 StringTokenizer类实例st,并分析str字符串有多少字符串子段;代码第26行,实例st调用 countTokens()方法获得子段(单词)的个数,StringTokenizer类的详细使用请参考第7章。

7.4.3 Java的事件处理类
运行结果】 (显示如图所示的窗口,当在文本框中输入句子时,标签中会显示句子中单词的个数。)

【代码说明】 类实现了接口TextListener,用以文本变化产生的事件,因此代码第19行,重写了接口的方法 textValueChanged()。代码第15行,为文本框t1注册了监听器; 代码第21行,判断事件源t1是否被触发;代码第24行,以空格、单引号、句号、问号做为分隔符创建 StringTokenizer类实例st,并分析str字符串有多少字符串子段;代码第26行,实例st调用 countTokens()方法获得子段(单词)的个数,StringTokenizer类的详细使用请参考第7章。

7.4.3 Java的事件处理类
运行结果】 (显示如图所示的窗口,当在文本框中输入句子时,标签中会显示句子中单词的个数。)

【代码说明】 类实现了接口TextListener,用以文本变化产生的事件,因此代码第19行,重写了接口的方法 textValueChanged()。代码第15行,为文本框t1注册了监听器; 代码第21行,判断事件源t1是否被触发;代码第24行,以空格、单引号、句号、问号做为分隔符创建 StringTokenizer类实例st,并分析str字符串有多少字符串子段;代码第26行,实例st调用 countTokens()方法获得子段(单词)的个数,StringTokenizer类的详细使用请参考第7章。

7.4.3 Java的事件处理类
运行结果】 (显示如图所示的窗口,当在文本框中输入句子时,标签中会显示句子中单词的个数。)

【代码说明】 类实现了接口TextListener,用以文本变化产生的事件,因此代码第19行,重写了接口的方法 textValueChanged()。代码第15行,为文本框t1注册了监听器; 代码第21行,判断事件源t1是否被触发;代码第24行,以空格、单引号、句号、问号做为分隔符创建 StringTokenizer类实例st,并分析str字符串有多少字符串子段;代码第26行,实例st调用 countTokens()方法获得子段(单词)的个数,StringTokenizer类的详细使用请参考第7章。




友情链接: