java语言学习后续.ppt

上传人:hs****ma 文档编号:567952659 上传时间:2024-07-22 格式:PPT 页数:301 大小:1.19MB
返回 下载 相关 举报
java语言学习后续.ppt_第1页
第1页 / 共301页
java语言学习后续.ppt_第2页
第2页 / 共301页
java语言学习后续.ppt_第3页
第3页 / 共301页
java语言学习后续.ppt_第4页
第4页 / 共301页
java语言学习后续.ppt_第5页
第5页 / 共301页
点击查看更多>>
资源描述

《java语言学习后续.ppt》由会员分享,可在线阅读,更多相关《java语言学习后续.ppt(301页珍藏版)》请在金锄头文库上搜索。

1、第第7章章 图形用户界面的设计与实现图形用户界面的设计与实现7.1 图形用户界面概述图形用户界面概述7.2 用户自定义成分用户自定义成分7.3 Java的事件处理的事件处理7.4 GUI标准组件概述标准组件概述7.5 标签、按钮与动作事件标签、按钮与动作事件7.6 文本框、文本区域与文本事件文本框、文本区域与文本事件7.7 单、复选按钮,列表与选择事件单、复选按钮,列表与选择事件7.8 滚动条与调整事件滚动条与调整事件7.9 画布与鼠标、键盘事件画布与鼠标、键盘事件7.10 布局设计布局设计7.11 Panel与容器事件与容器事件7.12 Frame与窗口事件与窗口事件7.13 菜单的定义与使

2、用菜单的定义与使用7.14 对话框、组件事件与焦点事件对话框、组件事件与焦点事件7.15 小结小结习题习题 本本章章介介绍绍Java程程序序中中图图形形用用户户界界面面(GUI)的的设设计计与与实实现现。图图形形用用户户界界面面是是程程序序与与用用户户交交互互的的窗窗口口。每每个个图图形形界界面面下下的的Java程程序序都都必必须须设设计计、建建立立自自己己的的图图形形用用户户界界面面并并利利用用它它接接受受用用户户的的输输入入,向向用用户户输输出出程程序序运运行行的的结结果果。本本章章将将介介绍绍图图形形用用户户界界面面的的基基本本组组成成和和主主要要操操作作,包包括括绘绘制制图图形形,显显

3、示示动动画画,使使用用AWT包各组件和实现包各组件和实现Java的事件处理功能等。的事件处理功能等。7.1 图形用户界面概述图形用户界面概述设设计计和和构构造造用用户户界界面面,是是软软件件开开发发中中的的一一项项重重要要工工作作。用用户户界界面面是是计计算算机机的的使使用用者者用用户户与与计计算算机机系系统统交交互互的的接接口口,用用户户界界面面功功能能是是否否完完善善,使使用用是是否否方方便便,将将直直接接影影响响到到用用户户对对应应用用软软件件的的使使用用。图图形形用用户户界界面面(graphics user interface)简简称称GUI,使使用用图图形形的的方方式式借借助助菜菜单

4、单、按按钮钮等等标标准准界界面面元元素素和和鼠鼠标标操操作作,帮帮助助用用户户方方便便地地向向计计算算机机系系统统发发出出命命令令,启启动动操操作作,并并将将系系统统运运行行的的结结果果同同样样以以图图形形的的方方式式显显示示给给用用户户。图图形形用用户户界界面面操操作作简简便便,省省去去了了字字符符界界面面用用户户必必须须记记忆忆各各种种命命令令的的麻麻烦烦,已已经经成成为为目目前前几几乎乎所所有有应应用用软软件件的的既既成成标标准准。所所以以,学学习习设设计计和和开开发发图形用户界面,是软件开发人员必修的一课。图形用户界面,是软件开发人员必修的一课。随随着着图图形形用用户户界界面面的的普普

5、及及和和界界面面元元素素标标准准化化程程度度的的提提高高,许许多多辅辅助助设设计计和和实实现现图图形形用用户户界界面面的的方方法法和和工工具具也也相相应应出出现现,例例如如,可可视视化化编编程程方方法法允允许许设设计计人人员员直直接接绘绘出出图图形形界界面面,然然后后交交给给专专门门的的工工具具自自动动编编码码生生成成这这个个图图形形界界面面,免免除除了了开开发发者者的的许许多多编编程程负负担担,目目前前许许多多应应用用软软件件开开发发工工具具都都具具有有可可视视化化编编程程的功能。的功能。Java语语言言中中,为为了了方方便便图图形形用用户户界界面面的的开开发发,设设计计了了专专门门的的类类

6、库库来来生生成成各各种种标标准准图图形形界界面面元元素素和和处处理理图图形形界界面面的的各各种种事事件件。这这个个用用来来生生成成图图形形用用户户界界面面的的类类 库库 就就 是是 java.awt包包 。 AWT是是 abstract window toolkit(抽象窗口工具集抽象窗口工具集)的缩写。的缩写。 所所谓谓抽抽象象,是是因因为为Java是是一一种种跨跨平平台台的的语语言言,要要求求Java程程序序能能在在不不同同的的平平台台系系统统上上运运行行,这这对对于于图图形形用用户户界界面面尤尤其其困困难难。为为了了达达到到这这个个目目标标,AWT类类库库中中的的各各种种操操作作被被定定

7、义义成成在在一一个个并并不不存存在在的的“抽抽象象窗窗口口”中中进进行行。正正如如Java虚虚拟拟机机使使得得Java程程序序独独立立于于具具体体的的软软硬硬件件平平台台一一样样,“抽抽象象窗窗口口”使使得得开开发发人人员员所所设设计计的的界界面面独独立立于于具具体体的的界界面面实实现现。也也就就是是说说,开开发发人人员员用用AWT开开发发出出的的图图形形用用户户界界面面可可以以适适用用于于所所有有的的平平台台系系统统。当当然然,这这仅仅是是理理想想情情况况。实实际际上上AWT的的功功能能还还不不是是很很完完全全,Java程程序序的的图图形形用用户户界界面面在在不不同同的的平平台台上上(例例如

8、如,在在不不同同的的浏浏览览器器中中)可可能能会会出出现现不不同同的的运运行行效效果果,如如窗窗口口大大小小、字体效果将发生变化等。字体效果将发生变化等。首先考察一下图形用户界面的构成。首先考察一下图形用户界面的构成。简单地说,图形用户界面就是一组图形界面成分和界简单地说,图形用户界面就是一组图形界面成分和界面元素的有机组合,这些成分和元素之间不但外观面元素的有机组合,这些成分和元素之间不但外观上有着包含、相邻、相交等物理关系,内在的也有上有着包含、相邻、相交等物理关系,内在的也有包含、调用等逻辑关系,它们互相作用、传递消息,包含、调用等逻辑关系,它们互相作用、传递消息,共同组成一个能响应特定

9、事件、具有一定功能的图共同组成一个能响应特定事件、具有一定功能的图形界面系统。形界面系统。设计和实现图形用户界面的工作主要有两个:设计和实现图形用户界面的工作主要有两个: 创建组成界面的各成分和元素,指定它们的属性创建组成界面的各成分和元素,指定它们的属性和位置关系,根据具体需要排列它们,从而构成完和位置关系,根据具体需要排列它们,从而构成完整的图形用户界面的物理外观。整的图形用户界面的物理外观。 定义图形用户界面的事件和各界面元素对不同事定义图形用户界面的事件和各界面元素对不同事件的响应,从而实现图形用户界面与用户的交互功件的响应,从而实现图形用户界面与用户的交互功能。能。Java中构成图形

10、用户界面的各种元素和成分可以粗略中构成图形用户界面的各种元素和成分可以粗略地被分为三类:容器、控制组件和用户自定义成分。地被分为三类:容器、控制组件和用户自定义成分。1. 容器容器容器是用来组织其他界面成分和元素的单元。一般说容器是用来组织其他界面成分和元素的单元。一般说来一个应用程序的图形用户界面首先对应于一个复来一个应用程序的图形用户界面首先对应于一个复杂的容器,如一个窗口。这个容器内部将包含许多杂的容器,如一个窗口。这个容器内部将包含许多界面成分和元素,这些界面元素本身也可能又是一界面成分和元素,这些界面元素本身也可能又是一个容器,这个容器再进一步包含它的界面成分和元个容器,这个容器再进

11、一步包含它的界面成分和元素,依此类推就构成一个复杂的图形界面系统。素,依此类推就构成一个复杂的图形界面系统。容器的引入有利于分解图形用户界面的复杂性,当界容器的引入有利于分解图形用户界面的复杂性,当界面的功能较多时,使用层层相套的容器是非常有必面的功能较多时,使用层层相套的容器是非常有必要的。要的。2. 控制组件控制组件与容器不同,控制组件是图形用户界面的最小单位之与容器不同,控制组件是图形用户界面的最小单位之一,它里面不再包含其他的成分。控制组件的作用一,它里面不再包含其他的成分。控制组件的作用是完成与用户的一次交互,包括接收用户的一个命是完成与用户的一次交互,包括接收用户的一个命令令(如菜

12、单命令如菜单命令),接收用户的一个文本或选择输入,接收用户的一个文本或选择输入,向用户显示一段文本或一个图形,等等。从某种程向用户显示一段文本或一个图形,等等。从某种程度上来说,控制组件是图形用户界面标准化的结果,度上来说,控制组件是图形用户界面标准化的结果,目前常用的控制组件有选择类的单选按钮、复选按目前常用的控制组件有选择类的单选按钮、复选按钮、下拉列表;有文字处理类的文本框、文本区域;钮、下拉列表;有文字处理类的文本框、文本区域;有命令类的按钮、菜单等。其中文本框、按钮和标有命令类的按钮、菜单等。其中文本框、按钮和标签是前面使用过的签是前面使用过的GUI组件。组件。使用控制组件,通常需要

13、如下的步骤:使用控制组件,通常需要如下的步骤:(1) 创建某控制组件类的对象,指定其大小等属性。创建某控制组件类的对象,指定其大小等属性。(2) 使用某种布局策略,将该控制组件对象加入到某使用某种布局策略,将该控制组件对象加入到某个容器中的某指定位置处。个容器中的某指定位置处。(3) 将该组件对象注册给它所能产生的事件对应的事将该组件对象注册给它所能产生的事件对应的事件监听者,重载事件处理方法,实现利用该组件对件监听者,重载事件处理方法,实现利用该组件对象与用户交互的功能。象与用户交互的功能。严格说来,容器也是一种控制组件,因为一个容器也严格说来,容器也是一种控制组件,因为一个容器也可以被视为

14、组件而包含在其他容器的内部。可以被视为组件而包含在其他容器的内部。3. 用户自定义成分用户自定义成分除了上述的标准图形界面元素,编程人员还可以根据除了上述的标准图形界面元素,编程人员还可以根据用户的需要设计一些用户自定义的图形界面成分,用户的需要设计一些用户自定义的图形界面成分,例如绘制一些几何图形、使用标志图案等。用户自例如绘制一些几何图形、使用标志图案等。用户自定义成分由于不能像标准界面元素一样被系统识别定义成分由于不能像标准界面元素一样被系统识别和承认,所以通常只能起到装饰、美化的作用,而和承认,所以通常只能起到装饰、美化的作用,而不能响应用户的动作,也不具有交互功能。不能响应用户的动作

15、,也不具有交互功能。7.2 用户自定义成分用户自定义成分本本节节主主要要介介绍绍如如何何利利用用Java类类库库中中的的类类及及其其方方法法来来绘绘制制用用户户自自定定义义的的图图形形界界面面成成分分。编编程程人人员员可可以以利利用用这这些些方方法法自自由由地地绘绘制制图图形形和和文文字字,也也可可以以将将已已经经存存在在的的图图形形、动动画画等等加加载载到到当当前前程程序序中中来来。绘绘制制图图形形和文字将要用到前面已经接触过的类和文字将要用到前面已经接触过的类Graphics。Graphics是是java.awt包包中中一一个个类类,其其中中包包括括了了很很多多绘绘制制图图形形和和文文字字

16、的的方方法法。当当一一个个Applet运运行行时时,执执行行它它的的浏浏览览器器会会自自动动为为它它创创建建一一个个Graphics类类的的实实例例,利利用用这这个个实实例例,就就可可以以在在Applet中中随随意意绘绘制制图图形形和和文文字字。实实际际上上Applet本本身身就就是是一一个个图图形形界界面面的的容容器器。而而如如果果希希望望在在图图形形界界面面的的Java Application程程序序中中绘绘制制图图形形,则则需需要要创创建建一一个个Canvas类类的的对对象象加加入入到到这这个个Application程程序序的的图图形形界界面面容容器器中中,Canvas对对象象也也拥拥有

17、有一一个个与与Applet类类的的paint( )方方法法相相同同的的paint( )方方法法,利利用用系系统统传传递递给给这这个个paint( )方方法法的的Graphics类类参参数数对对象象就就可可以以在在Application程程序序的的图图形形用用户户界界面中绘制各种图形和文字。面中绘制各种图形和文字。7.2.1 绘制图形绘制图形利用利用Graphics类可绘制的图形有直线、各种矩形、多类可绘制的图形有直线、各种矩形、多边形、圆和椭圆等。下面的例子综合了这些方法。边形、圆和椭圆等。下面的例子综合了这些方法。例例 7-1 DrawFigures.java 1: import java.

18、awt.*;2: import java.applet.Applet;3: public class DrawFigures extends Applet4: 5: public void paint ( Graphics g)6: 7: g.drawLine(30,5,40,5); /画直线画直线8: g.drawRect(40,10,50,20);/画矩形框画矩形框(左上角左上角x坐标,坐标, 左上角左上角y坐标,坐标,x轴尺寸,轴尺寸,y轴尺寸轴尺寸)9: g.fillRect(60,30,70,40); /画实心矩形画实心矩形10: g.drawRoundRect(110,10,130

19、,50,30,30); /画圆角矩画圆角矩形框形框11: g.drawOval(150,120,70,40); /画椭圆形框画椭圆形框(左上角左上角x坐标,左上角坐标,左上角y坐标,坐标,x轴尺寸,轴尺寸,y轴尺寸轴尺寸),若,若x轴尺寸与轴尺寸与y轴尺寸相等,则画出圆形轴尺寸相等,则画出圆形12: g.fillOval(190,160,70,40); /画实心椭圆画实心椭圆13: g.drawOval(90,100,50,40); /画椭圆框画椭圆框14: g.fillOval(130,100,50,40); /画实心椭圆画实心椭圆15: drawMyPolygon(g); /自定义的画多边

20、形的方法自定义的画多边形的方法16: g.drawString(They are figures!,100,220); 17: 18: public void drawMyPolygon( Graphics g)19: 20: int xCoords = 30,50,65,119,127; /保存多边形各点保存多边形各点x坐标的数组坐标的数组21: int yCoords = 100, 140,127,169,201; /保存多边形各点保存多边形各点y坐标的数组坐标的数组22: g.drawPolygon( xCoords,yCoords,5); /画自由多边形框画自由多边形框23: 24:

21、图图7.1是是例例7-1的的运运行行结结果果。从从例例7-1可可以以看看出出,要要在在Java程程序序图图形形界界面面的的容容器器中中绘绘制制图图形形,首首先先,需需要要明明确确希希望望绘绘制制的的图图形形是是什什么么,是是圆圆、椭椭圆圆,还还是是直直线线,这这由由所所选选定定的的方方法法来来确确定定;其其次次,需需要要指指明明所所绘绘制制图图形形或或文文字字的的大大小小和和位位置置,这这要要通通过过相相对对于于界界面面容容器器的的二二维维像像素素坐坐标标来来决决定定。Java的的屏屏幕幕坐坐标标是是以以像像素素为为单单位位,容容器器的的左左上上角角被被确确定定为为横横坐坐标标(x轴轴)和纵坐

22、标和纵坐标(y轴轴)的起点,向右和向下延伸坐标值递增。的起点,向右和向下延伸坐标值递增。 图图 7.1 例例7-1的运行结果的运行结果绘制图形的方法很多,每种方法一般也有多种灵活的绘制图形的方法很多,每种方法一般也有多种灵活的使用方式,这里不再赘述,读者可以查阅程序员手使用方式,这里不再赘述,读者可以查阅程序员手册中的详细规定。册中的详细规定。除了除了Graphics类,类,Java中还定义了其他一些用来表示中还定义了其他一些用来表示几何图形的类,对绘制用户自定义成分也很有帮助。几何图形的类,对绘制用户自定义成分也很有帮助。例如,利用例如,利用Point表示一个像素点;利用表示一个像素点;利用

23、Dimension类表示宽和高;利用类表示宽和高;利用Rectangle类表示一个矩形;利类表示一个矩形;利用用Polygon类表示一个多边形;利用类表示一个多边形;利用Color类表示颜类表示颜色等,后面的例子中将利用这些系统定义的类绘图。色等,后面的例子中将利用这些系统定义的类绘图。7.2.2 显示文字显示文字从从前前面面的的例例子子中中可可以以知知道道,Graphics类类的的方方法法drawString( )可可以以在在屏屏幕幕的的指指定定位位置置显显示示一一个个字字符符串串。Java中中还还有有一一个个类类Font,使使用用它它可可以以获获得得更更加加丰丰富富多多彩彩和和逼真精确的字

24、体显示效果。逼真精确的字体显示效果。一一个个Font类类的的对对象象表表示示了了一一种种字字体体显显示示效效果果,包包括括字字体体类类型型、字字型型和和字字号号。下下面面的的语语句句用用于于创创建建一一个个Font类的对象:类的对象: Font MyFont = new Font ( TimesRoman, Font.BOLD, 12 ); MyFont对应的是对应的是12磅磅TimesRoman类型的黑体字,类型的黑体字,其中指定字型时需要用到其中指定字型时需要用到Font类的三个常量:类的三个常量:Font.PLAIN, Font.BOLD, Font.ITALIC。如果希望使用该如果希望

25、使用该Font对象,则可以利用对象,则可以利用Graphics类的类的setFont( )方法:方法: g. setFont ( MyFont );如果希望指定控制组件,如按钮或文本框中的字体效如果希望指定控制组件,如按钮或文本框中的字体效果,则可以使用控制组件的方法果,则可以使用控制组件的方法setFont( )。如设。如设btn是一个按钮对象,则语句:是一个按钮对象,则语句: btn.setFont(MyFont);将把这个按钮上显示的标签的字体改为将把这个按钮上显示的标签的字体改为12磅的磅的TimesRoman黑体字。黑体字。另外,与另外,与setFont( )方法相对的方法相对的ge

26、tFont( )方法将返回方法将返回当前当前Graphics或组件对象使用的字体。或组件对象使用的字体。例例 7-2 AvailableFonts.java1: import java.applet.*;2: import java.awt.*;3:4: public class AvailableFont extends Applet5: 6: GraphicsEnvironment gl = GraphicsEnvironment.getLocalGraphicsEnvironment( );7: String FontNames = gl.getAvailableFontFamilyNa

27、mes( );8:9: public void paint(Graphics g)10: 11: Font current,oldFont;12: 13: oldFont = g.getFont( );14: for(int i=0;iFontNames.length;i+)15: 16: current = new Font(FontNamesi,Font.PLAIN,10);17: g.setFont(current);18: g.drawString(current.getName( ),10+i%4*120,20+i/4*15);19: 20: g.setFont(oldFont);2

28、1: 22: 在在 例例 7-2中中 , 首首 先先 在在 第第 6句句 利利 用用 java.awt包包 的的GraphicsEnvironment类类的的静静态态方方法法getLocalGraphicsEnvironment( )获获得得代代表表Java程程序序运运行行的的当当前前平平台台的的图图形形环环境境的的对对 象象 gl, 然然 后后 在在 第第 7句句 调调 用用 gl对对 象象 的的 getAvailableFontFamilyNames( )获获得得当当前前平平台台上上所所有有可可以以使使用用的的字字体体名名字字,返返回回给给字字符符串串数数组组FontNames,该该数数组

29、组的的每每个个元元素素是是一一代代表表字字体体名名的的字字符符串串。第第13句句首首先先获获取取并并保保存存当当前前缺缺省省的的字字体体对对象象。第第14到到19句句的的循循环环修修改改当当前前字字体体,设设置置成成一一可可用用的的字字体体并并输输出出该该字字体体的的名名称称,每每四四个个字字体体占占用用一一行行;其其中中第第16句句使使用用Font类类的的构构造造函函数数创创建建新新字字体体对对象象。最最后后,第第20句句把把字字体体恢恢复复成原来的缺省值。例成原来的缺省值。例7-2的运行结果如图的运行结果如图7.2所示。所示。 图图 7.2 例例7-2的运行结果的运行结果 7.2.3 控制

30、颜色控制颜色Applet中显示的字符串或图形的颜色可以用中显示的字符串或图形的颜色可以用Color类类的对象来控制,每个的对象来控制,每个Color对象代表一种颜色,用对象代表一种颜色,用户可以直接使用户可以直接使用Color类中定义好的颜色常量,也类中定义好的颜色常量,也可以通过调配红、绿、蓝三色的比例创建自己的可以通过调配红、绿、蓝三色的比例创建自己的Color对象。对象。Color类中定义有如下的三种构造函数:类中定义有如下的三种构造函数:public Color(int Red, int Green, int Blue);public Color(float Red, float Gr

31、een, float Blue);public Color(int RGB); 不不论论使使用用哪哪个个构构造造函函数数创创建建Color对对象象,都都需需要要指指定定新新建建颜颜色色中中R(红红)、G(绿绿)、B(蓝蓝)三三色色的的比比例例。在在第第一一个个构构造造函函数数中中通通过过三三个个整整型型参参数数指指定定R,G,B,每每个个参参数数的的取取值值范范围围在在0255之之间间;第第二二个个构构造造函函数数通通过过三三个个浮浮点点参参数数指指定定R,G,B,每每个个参参数数的的取取值值范范围围在在0.01.0之之间间;第第三三个个构构造造函函数数通通过过一一个个整整型型参参数数指指明明

32、其其RGB三三色色比比例例,这这个个参参数数的的07比比特特(取取值值范范围围为为0255)代代表表红红色色的的比比例例,815比比特特代代表表绿绿色色的的比比例例,1623比比特特代代表表蓝蓝色色的的比比例例。例例如下面的语句创建的是蓝色:如下面的语句创建的是蓝色:Color blueColor = new Color(0,0,255); 调调用用Graphics对对象象的的setColor( )方方法法可可以以把把当当前前的的缺缺省省颜颜色色修修改改成成新新建建的的颜颜色色,使使此此后后调调用用该该Graphics对对象象完完成成的的绘绘制制工工作作,如如绘绘制制图图形形、字字符符串串等等

33、,都都使用这个新建颜色:使用这个新建颜色: g.setColor(blueColor);除除了了创创建建自自己己的的颜颜色色,也也可可以以直直接接使使用用Color类类中中定定义好的颜色常量,如:义好的颜色常量,如: g.setColor(Color.cyan);Color类类中中共共定定义义了了13种种静静态态颜颜色色常常量量,包包括括black,orange,pink,grey等等,使使用用时时只只需需以以Color为为前前缀缀,非常方便。非常方便。 对于对于GUI的控制组件,它们有四个与颜色有关的方法的控制组件,它们有四个与颜色有关的方法分别用来设置和获取组件的背景色和前景色:分别用来设

34、置和获取组件的背景色和前景色:public void setBackground(Color c)public Color getBackground( )public void setForeground( )public Color getForeground( ) 例例 7-3 UseColor.java1: import java.applet.Applet;2: import java.awt.*;3:4: public class UseColor extends Applet5: 6: Color oldColor; 7: String ParamName = red,green

35、,blue; /三个三个HTML参数的名称参数的名称8: int RGBarray = new int3; /保存三色比例的数组保存三色比例的数组9:10: public void init( )11: 12: for(int i=0;iParamName.length;i+) /取得取得HTML文件指定的三色文件指定的三色13: RGBarrayi = Integer.parseInt(getParameter(ParamNamei);14: 15: public void paint(Graphics g)16: 17: oldColor = g.getColor( ); /保存原有的缺省

36、颜色保存原有的缺省颜色18: g.setColor(new Color(RGBarray0,RGBarray1,RGBarray2); /置新颜色置新颜色19: g.drawString(How do you think about Current color:20: + g.getColor( ).toString( ),10,20); /用新建颜用新建颜色显示该颜色的三色分量色显示该颜色的三色分量21: g.setColor(oldColor); /恢复原有颜色恢复原有颜色22: g.drawString(Back to old default color:+ g.getColor( ).

37、toString( ),10,40);23: 24: 例例7-3的运行结果如图的运行结果如图7.3所示。所示。例例7-3利利用用HTML文文件件传传递递给给Java Applet的的三三个个参参数数作作为为R,G,B三三色色的的比比例例。第第18句句用用该该比比例例创创建建颜颜色色,并并用用新新颜颜色色显显示示字字符符串串(包包括括新新颜颜色色中中三三色色的的比例含量比例含量)。第。第21句再恢复原来的缺省颜色。句再恢复原来的缺省颜色。 图图 7.3 例例7-3的运行结果的运行结果 此程序对应的此程序对应的HTML文件如下:文件如下:UseColor 通通过过改改变变三三个个参参数数的的数数值

38、值(应应在在0255之之间间),就就可可以以指定不同的颜色而不需要重新编译指定不同的颜色而不需要重新编译Java Applet程序。程序。 7.2.4 显示图像显示图像由于图像的数据量要远远大于图形,所以一般不在程由于图像的数据量要远远大于图形,所以一般不在程序中自行绘制图像,而是把已经存在于本机硬盘或序中自行绘制图像,而是把已经存在于本机硬盘或网络某地的二进制图像文件直接调入内存。图像文网络某地的二进制图像文件直接调入内存。图像文件有多种格式,如件有多种格式,如bmp文件、文件、gif文件、文件、tiff文件等文件等等,其中等,其中gif是是Internet上常用的图像文件格式。上常用的图像

39、文件格式。Java中可以利用中可以利用Graphics类的类的drawImage( )方法显示方法显示图像,现考察下面的例子。图像,现考察下面的例子。例例 7-4 DrawMyImage.java 1: import java.awt.*;2: import java.applet.Applet;3: public class DrawMyImage extends Applet4: 5: Image myImage ;6: public void init( )7: 8: myImage = getImage(getDocumentBase( ), blackbrd.gif );9: 10:

40、 public void paint(Graphics g)11: 12: g.drawImage(myImage, 0, 0, this );13: 14: 例例7-4中,使用了中,使用了Image类的对象类的对象myImage来保存二进来保存二进制的图像数据,其中制的图像数据,其中getImage( )方法是系统为方法是系统为Applet类定义的方法,该方法将指定图像文件的内类定义的方法,该方法将指定图像文件的内容加载到内存的容加载到内存的Image对象中。对象中。getImage( )方法有两方法有两个参数。第一个是图像文件所在的个参数。第一个是图像文件所在的URL地址,在上地址,在上例

41、中由于图像文件与例中由于图像文件与HTML文件保存在同一路径下,文件保存在同一路径下,所以用所以用Applet类另一个方法类另一个方法getDocumentBase( )来获来获取含有该取含有该Applet的的HTML文件的文件的URL地址。地址。getImage( ) 的第二个参数是图像文件的文件名。的第二个参数是图像文件的文件名。Java可识别可识别的图像文件格式有的图像文件格式有bmp,gif,jpeg等。等。 drawImage( )是是Graphics类类中中用用来来显显示示图图像像的的方方法法。它它的的第第一一个个参参数数是是保保存存有有图图像像数数据据的的Image对对象象。第第

42、二二、第第三三个个参参数数是是图图像像的的左左上上角角点点坐坐标标,它它们们决决定定了了图图像像在在容容器器中中的的显显示示位位置置。最最后后一一个个参参数数是是显显示示图图像像的的容容器器对对象象。例例7-4中中的的this代代表表了了当当前前的的Applet对象。对象。 7.2.5 实现动画效果实现动画效果动动画画曾曾是是Java Applet最最吸吸引引人人的的特特性性之之一一。用用Java实实现现动动画画的的原原理理与与放放映映动动画画片片类类似似,取取若若干干相相关关的的图图像像或或图图片片,顺顺序序、连连续续地地在在屏屏幕幕上上先先显显示示,后后擦擦除除,循循环环往往复复就就可可以

43、以获获得得动动画画的的效效果果。参参考考下下面面的的例子。例子。例例 7-5 ShowAnimator.java 1: import java.applet.Applet;2: import java.awt.*;3:4: public class ShowAnimator extends Applet5: 6: Image m-Images;/保存图片序列的保存图片序列的Image数组数组7: int totalImages = 18; /图片序列中的图片总数图片序列中的图片总数8: int currentImage = 0; /当前时刻应该显示的图片当前时刻应该显示的图片 序号序号9:10

44、: public void init( )11: 12: m-Images = new ImagetotalImages;13: /从当前目录下的从当前目录下的images子目录中将子目录中将Img001.gif到到 Img0018.gif的文件加载的文件加载14: for(int i=0;itotalImages;i+)15: m-Imagesi = getImage(getDocumentBase( ),imagesImg00+(i+1) + .gif);16: 17: public void start( )18: 19: currentImage = 0; /从第一幅开始显示从第一幅开

45、始显示20: 21: public void paint(Graphics g)22: 23: g.drawImage(m-ImagescurrentImage,50,50,this); /显示当前序号的显示当前序号的图片图片24: currentImage = +currentImage % totalImages; /计算下一个应显示图片的序号计算下一个应显示图片的序号25: try26: Thread.sleep(50); /程序休眠程序休眠50毫秒毫秒27: 28: catch(InterruptedException e) /处理执行休眠方法可能引发的异常处理执行休眠方法可能引发的异

46、常29: 30: showStatus(e.toString( );31: 32: repaint( ); /图片停留图片停留50毫秒后被擦除,重新调毫秒后被擦除,重新调 用用paint( )显示下一张图片显示下一张图片33: 34: 例例7-5中中使使用用了了Thread.sleep( )方方法法,目目的的是是使使当当前前的的程程序序线线程程休休眠眠一一段段时时间间,以以便便每每幅幅图图片片在在下下一一幅幅图图片片显显示示之之前前能能在在屏屏幕幕上上逗逗留留一一小小段段时时间间,关关于于线线程程的的具具体体编编程程将将在在以以后后的的章章节节详详细细介介绍绍。第第14句句到到第第15句句的的

47、循循环环使使用用Applet的的getImage( )方方法法获获取取所所有有的的.gif图图像像文文件件(注注意意其其目目录录)。第第21句句到到33句句的的paint( )方方法法一一次次显显示示一一幅幅图图像像,稍稍待待片片刻刻后后再再显显示示Image对对象象数数组组中中的的下下一一幅幅图图像像。图图7.4是是例例7-5的的运运行结果。行结果。 图图 7.4 例例7-5的运行结果的运行结果在在设设计计和和实实现现程程序序的的图图形形用用户户界界面面的的过过程程中中,绘绘制制用用户户自自定定义义成成分分仅仅仅仅完完成成了了一一部部分分工工作作,它它可可以以装装饰饰、美美化化用用户户界界面

48、面,但但却却无无法法接接收收程程序序运运行行过过程程中中的的即即时时用用户户指指令令,不不能能提提供供与与用用户户的的动动态态交交互互。Java中中用来解决这个问题的机制是事件及其处理。用来解决这个问题的机制是事件及其处理。7.3 Java的事件处理的事件处理图图形形用用户户界界面面之之所所以以能能为为广广大大用用户户所所喜喜爱爱并并最最终终成成为为事事实实上上的的标标准准,很很重重要要的的一一点点就就在在于于它它可可以以用用更更灵灵活活、简简便便的的方方式式来来接接收收用用户户命命令令。用用户户在在图图形形用用户户界界面面中中输输入入命命令令是是通通过过移移动动鼠鼠标标对对特特定定图图形形界

49、界面面元元素素单单击击、双双击击鼠鼠标标键键来来实实现现的的,为为了了能能够够接接收收用用户户的的命命令令,图图形形用用户户界界面面的的系系统统首首先先应应该该能能够够识识别别这这些鼠标和键盘的操作并做出相应的响应。些鼠标和键盘的操作并做出相应的响应。 通通常常每每一一个个键键盘盘或或鼠鼠标标操操作作会会引引发发一一个个系系统统预预先先定定义义好好的的事事件件,用用户户程程序序只只需需要要编编制制代代码码定定义义每每个个特特定定事事件件发发生生时时程程序序应应做做出出何何种种响响应应即即可可。这这些些代代码码会会在在它它们们对对应应的的事事件件发发生生时时由由系系统统自自动动调调用用,这这就就

50、是是图形用户界面中事件和事件响应的基本原理。图形用户界面中事件和事件响应的基本原理。Java中,除了键盘和鼠标操作,系统的状态改变、标中,除了键盘和鼠标操作,系统的状态改变、标准图形界面元素等都可以引发事件,对这些事件分准图形界面元素等都可以引发事件,对这些事件分别定义处理代码,就可以保证应用程序系统在不同别定义处理代码,就可以保证应用程序系统在不同的状况下都合理有效、有条不紊地正常工作。的状况下都合理有效、有条不紊地正常工作。Java的事件处理机制中引入了委托事件模型的事件处理机制中引入了委托事件模型(如图如图7.5所示所示),不同的事件由不同的监听者处理。,不同的事件由不同的监听者处理。图

51、图 7.5 委托事件模型委托事件模型图图7.5中中,图图形形用用户户界界面面的的每每个个可可能能产产生生事事件件的的组组件件被被称称为为事事件件源源,不不同同事事件件源源上上发发生生的的事事件件的的种种类类不不同同。例例如如,Button对对象象或或MenuItem对对象象等等作作为为事事件件源源可可能能引引发发ActionEvent类类代代表表的的事事件件ACTION-PERFORMED;Checkbox对对象象等等作作为为事事件件源源可可能能引引 发发 ItemEvent类类 代代 表表 的的 事事 件件 ITEM-STATE-CHANGES。希希望望事事件件源源上上发发生生的的事事件件被

52、被程程序序处处理理,就就要要把把事事件件源源注注册册给给能能够够处处理理该该事事件件源源上上那那种种类类型型事事件件的的监监听听者者。例例 如如 Button对对 象象 把把 自自 己己 注注 册册 给给 实实 现现 了了ActionListener接接口口的的对对象象,因因为为只只有有这这种种对对象象能能够够处处理理Button对对象象上上发发生生的的ActionEvent类类的的事事件件,监监听听者者可可以以是是包包容容事事件件源源的的容容器器,也也可可以以是是另另外外的的对对象象。具具体体的的注注册册方方法法是是通通过过调调用用事事件件源源本本身身的的相相关关方方法法,例例如如调调用用B

53、utton类类自自身身的的addActionListener( )方法,并以监听者对象作为实际参数来实现的。方法,并以监听者对象作为实际参数来实现的。监监听听者者之之所所以以成成为为监监听听者者,并并具具有有监监听听和和处处理理某某类类事事件件的的功功能能,是是因因为为它它实实现现了了有有关关的的接接口口,所所以以监监听听者者需需要要对对它它所所实实现现接接口口的的所所有有抽抽象象方方法法写写出出具具体体的的方方法法体体,对对应应事事件件源源上上发发生生的的事事件件的的处处理理代代码码就就写写在在这这些些方方法法体体里里。例例如如对对Button上上发发生生的的事事件件的的处处理理 代代 码码

54、 应应 该该 写写 在在 Button对对 象象 所所 注注 册册 的的 监监 听听 者者 的的 actionPerformed( )方方法法中中,这这个个方方法法是是对对ActionListener接接口口中中同同名抽象方法的具体实现。名抽象方法的具体实现。当事件源上发生监听者可以处理的事件时,事件源把当事件源上发生监听者可以处理的事件时,事件源把这个事件作为实际参数传递给监听者中负责处理这这个事件作为实际参数传递给监听者中负责处理这类事件的方法类事件的方法(委托委托),这个方法被系统自动调用执,这个方法被系统自动调用执行后,事件就得到了处理。行后,事件就得到了处理。这里,监听者并不一定是包

55、容事件源的容器对象,这这里,监听者并不一定是包容事件源的容器对象,这样处理使得程序中的事件处理代码与样处理使得程序中的事件处理代码与GUI界面构成界面构成代码得以分离,有利于优化程序结构;另外,由于代码得以分离,有利于优化程序结构;另外,由于Java对事件作了详细的分类并委托不同的接口方法对事件作了详细的分类并委托不同的接口方法加以处理,使得代码性能得到提高。加以处理,使得代码性能得到提高。Java的所有事件类和处理事件的监听者接口都定义在的所有事件类和处理事件的监听者接口都定义在java.awt.event包中,其中事件类的层次结构如图包中,其中事件类的层次结构如图7.6所示。所示。图图 7

56、.6 AWTEvent类体系结构图类体系结构图这这个个体体系系结结构构图图中中包包括括的的事事件件类类很很多多,它它们们都都是是java.awt.AWTEvent类类的的子子类类,而而java.awt.AWTEvent类类则则是是java.util.EventObject类类的的子子类类。EventObject有有一一个个重重要要的的方方法法getSource( )在在前前面面已已经经使使用用过过,该该方方法法返返回回产产生生事事件件的的事事件件源源,几几乎乎所所有有的的事事件件类类都都要要用用到到这这个个方方法法。需需要要注注意意的的是是,并并非非每每个个事事件件类类都都只只对对应应一一个个

57、事事件件,例例如如KeyEvent类类可可能能对对应应KEY-PRESSED(键键按按下下)、KEY-RELEASED(键键松松开开)、KEY-TYPED(击击键键)三三个具体的事件。个具体的事件。判判断断一一个个KeyEvent类类的的对对象象到到底底代代表表哪哪种种事事件件,可可以以调调用用它它的的getID( )方方法法并并把把方方法法的的返返回回值值与与KEY-PRESSED等等几几个个常常量量相相比比较较。每每个个事事件件类类的的对对象象都都 拥拥 有有 getID( )方方 法法 , 是是 它它 们们 从从 共共 同同 的的 父父 类类AWTEvent那里继承来的。那里继承来的。j

58、ava.awt.event包包中中还还定定义义了了11个个监监听听者者接接口口,每每个个接接口口内内部部包包含含了了若若干干处处理理相相关关事事件件的的抽抽象象方方法法。一一般般说说来来,每每个个事事件件类类都都有有一一个个监监听听者者接接口口与与之之相相对对应应,而而事事件件类类中中的的每每个个具具体体事事件件类类型型都都有有一一个个具具体体的的抽抽象象方方法法与与之之相相对对应应,当当具具体体事事件件发发生生时时,这这个个事事件件将将被被封封装装成成一一个个事事件件类类的的对对象象作作为为实实际际参参数数传传递递给给与与之之对对应应的的具具体体方方法法,由由这这个个具具体体方方法法负负责责

59、响响应应并并处处理理发发生生的的事事件件。例例如如与与ActionEvent类类事事件件对对应应的的接接口口是是ActionListener,这这个个接接口口定定义义了了抽抽象方法:象方法: public void actionPerformed(ActionEvent e); 凡凡 是是 要要 处处 理理 ActionEvent事事 件件 的的 类类 都都 必必 须须 实实 现现ActionListener接接口口,实实现现ActionListener接接口口就就必必须须重重载载上上述述的的actionPerformed()方方法法,在在重重载载的的方方法法体体中中,通通常常需需要要调调用用

60、参参数数e的的有有关关方方法法。例例如如调调用用e.getSource查查明明产产生生ActionEvent事事件件的的事事件件源源,然后再采取相应的措施处理该事件。然后再采取相应的措施处理该事件。比比较较特特殊殊的的情情况况有有两两个个:一一个个是是InputEvent类类,因因为为它它不不对对应应具具体体的的事事件件,所所以以没没有有监监听听者者与与之之相相对对应应;另另一一个个是是MouseEvent类类,它它有有两两个个监监听听者者接接口口与与之之相相对对应应,一一个个是是MouseListener接接口口(其其中中的的方方法法可可以以响响应应MOUSE_CLICKED,MOUSE_E

61、NTERED,MOUSE_EXITED,MOUSE_PRESSED,MOUSE_RELEASED五五个个具具体体事事件件),另另一一个个是是MouseMotionListener接接口口(其其中中的的方方法法可可以以响响应应MOUSE_DRAGGED,MOUSE_MOVED的的两两个个事事件件)。具具体体事事件件及及其其处处理将结合理将结合GUI组件详细介绍。组件详细介绍。7.4 GUI标准组件概述标准组件概述构构建建程程序序的的图图形形用用户户界界面面的的主主要要任任务务有有两两个个:一一是是创创建建各各界界面面组组件件并并排排列列成成图图形形用用户户界界面面的的物物理理外外观观;二二是是定

62、定义义这这些些组组件件对对不不同同事事件件的的响响应应从从而而完完成成图图形形用用户户界界面面功功能能。从从本本节节开开始始将将具具体体讨讨论论如如何何用用标标准准组组件件来来构构建建图图形形用用户户界界面面,以以及及定定义义这这些些组组件件对对事事件件的的响响应应,包包括括它它们们相相互互之之间间和和与与用用户户之之间间的的交交互互功能。功能。组组成成图图形形用用户户界界面面的的成成分分有有三三类类,前前面面已已讨讨论论过过其其中中的的用用户户自自定定义义成成分分,余余下下的的两两类类容容器器和和控控制制组组件件都都属属于于图图形形用用户户界界面面的的标标准准组组件件,一一般般说说来来,容容

63、器器是是能能够够容容纳纳并并排排列列其其他他组组件件的的对对象象,基基本本组组件件是是放放置置在在容容器器中中的的对对象象。在在Java中中,它它们们是是由由AWT包包中中的的对对象象来来代代表表的的。这这些些对对象象间间的的层层次次关关系系可可以以参参看看图图7.7,可可见见所所有有的的GUI标标准准组组件件都都是是java.awt.*包包中中的的根根类类Component类类的的子子类类,Component类类的的直直接接子子类类包包括括一一个个容容器器组组件件Container和和八八个个基基本本组组件,如件,如Button,Label,Choice,TextComponent等。等。

64、其中其中TextComponent可以细分为包含多行文本的可以细分为包含多行文本的TextArea和包含单行文本的和包含单行文本的TextField;Container是所有容器组件的根类,容器组件的作用是包容其是所有容器组件的根类,容器组件的作用是包容其他组件并按一定的方式组织排列它们,同一个容器他组件并按一定的方式组织排列它们,同一个容器中的所有部件通常总是同时被显示和同时被隐藏的。中的所有部件通常总是同时被显示和同时被隐藏的。从图从图7.7的的AWT组件体系结构中可以看出,所有的组件体系结构中可以看出,所有的容器组件都是容器组件都是Container类的子类,而类的子类,而Contain

65、er类类又是又是Component类的子类。作为类的子类。作为Container子类的子类的容器可分为三组:容器可分为三组:Panel和和Applet一组的容器是无一组的容器是无边框的;边框的;ScrollPanel一组是可以自动处理滚动操作一组是可以自动处理滚动操作的容器;的容器;Window,Frame,Dialog和和FileDialog是是一组大都含有边框,并可以移动、放大、缩小、关一组大都含有边框,并可以移动、放大、缩小、关闭的功能较强的容器。闭的功能较强的容器。图图 7.7 AWT组件层次关系图组件层次关系图 基本控制组件被安放在容器中的某个位置,用来完成基本控制组件被安放在容器中

66、的某个位置,用来完成一种具体地与用户交互的功能。使用基本控制组件一种具体地与用户交互的功能。使用基本控制组件一般包括如下的步骤:一般包括如下的步骤:(1) 创建某种基本控制组件类的新对象,指定该对象创建某种基本控制组件类的新对象,指定该对象的属性,如外观、大小等。的属性,如外观、大小等。(2) 将该组件对象加入到某个容器的合适位置。将该组件对象加入到某个容器的合适位置。(3) 创建该组件对象的监听者,即实现以该组件为事创建该组件对象的监听者,即实现以该组件为事件源的事件对应的监听者接口,也可以使现有的类件源的事件对应的监听者接口,也可以使现有的类实现该接口成为监听者。将该组件对象注册给此监实现

67、该接口成为监听者。将该组件对象注册给此监听者,并在监听者内部实现监听者接口中定义的方听者,并在监听者内部实现监听者接口中定义的方法,对该组件可能引发的事件加以处理,定义新加法,对该组件可能引发的事件加以处理,定义新加入的组件对象的交互性界面功能,如接收用户输入入的组件对象的交互性界面功能,如接收用户输入的文本或选择、做屏幕显示输出等。的文本或选择、做屏幕显示输出等。 Component类是所有组件和容器的抽象父类,其中定类是所有组件和容器的抽象父类,其中定义了一些每个容器和组件都可能用到的方法,较常义了一些每个容器和组件都可能用到的方法,较常用的有:用的有:(1) public void ad

68、d(PopupMenu popup): 在组件上在组件上加入一个弹出菜单,当用户用鼠标右键单击组件时加入一个弹出菜单,当用户用鼠标右键单击组件时将弹出这个菜单。将弹出这个菜单。(2) public Color getBackground( ): 获得组件的背景获得组件的背景色。色。(3) public Font getFont( ): 获得组件使用的字体。获得组件使用的字体。(4) public Color getForeground( ): 获得组件的前景获得组件的前景色。色。(5) public Graphics getGraphics( ): 获得在组件上绘获得在组件上绘图时需要使用的图

69、时需要使用的Graphics对象。对象。(6) public void repaint(int x, int y, int width, int height): 以指定的坐标点以指定的坐标点(x,y)为左上角,重画组为左上角,重画组件中指定宽度件中指定宽度(width)、指定高度、指定高度(height)的区域。的区域。(7) public void setBackground(Color c): 设置组件的设置组件的背景色。背景色。(8) public void setEnabled(boolean b): 设置组件的设置组件的使能状态。参数使能状态。参数b为真则组件使能,否则组件不使为真

70、则组件使能,否则组件不使能。只有使能状态的组件才能接受用户输入并引发能。只有使能状态的组件才能接受用户输入并引发事件。事件。(9) public void setFont(Font f): 设置组件使用的字设置组件使用的字体。体。(10) public void setSize(int width, int height): 设置设置组件的大小。组件的大小。(11) public void setVisible(boolean b): 设置组件是否设置组件是否可见的属性。参数可见的属性。参数b为真时,组件在包括它的容器为真时,组件在包括它的容器可见时也可见;否则组件不可见。可见时也可见;否则组

71、件不可见。(12) public void setForeground(Color c): 设置组件设置组件的前景色。的前景色。(13) public void requestFocus( ): 使组件获得注意的使组件获得注意的焦点。焦点。下面将从创建、常用方法和事件响应几个方面逐一介下面将从创建、常用方法和事件响应几个方面逐一介绍常用的绍常用的GUI组件和容器。组件和容器。7.5 标签、按钮与动作事件标签、按钮与动作事件1. 标签标签(Label)标签是用户不能修改只能查看其内容的文本显示区域,标签是用户不能修改只能查看其内容的文本显示区域,它起到信息说明的作用,每个标签用一个它起到信息说明

72、的作用,每个标签用一个Label类类的对象表示。的对象表示。(1) 创建标签创建标签创建标签对象时应同时说明这个标签中的字符串:创建标签对象时应同时说明这个标签中的字符串:Label prompt = new Label(请输入一个整数:请输入一个整数:); (2) 常用方法常用方法如果希望修改标签上显示的文本,则可以使用如果希望修改标签上显示的文本,则可以使用Label对象的方法对象的方法setText(新字符串新字符串),同样对于一个未知,同样对于一个未知的标签,可以通过调用的标签,可以通过调用Label对象的对象的getText( )方法方法来获得它的文本内容。例如下面的程序片断将修改来

73、获得它的文本内容。例如下面的程序片断将修改标签中的文本内容:标签中的文本内容:if(prompt.getText( )=你好你好)prompt.setText(再见再见);else if(prompt.getText( )=再见再见)prompt.setText(你好你好); (3) 产生事件产生事件标签不能接受用户的输入,所以不能引发事件。它不标签不能接受用户的输入,所以不能引发事件。它不是事件源。是事件源。2. 按钮按钮(Button)按钮是图形用户界面中非常重要的一种基本组件,按按钮是图形用户界面中非常重要的一种基本组件,按钮本身不显示信息,它一般对应一个事先定义好的钮本身不显示信息,它

74、一般对应一个事先定义好的功能操作,并对应一段程序。当用户点击按钮时,功能操作,并对应一段程序。当用户点击按钮时,系统自动执行与该按钮相联系的程序,从而完成预系统自动执行与该按钮相联系的程序,从而完成预先指定的功能。先指定的功能。(1) 创建创建下面的语句用来创建按钮,传递给构造函数的字符串下面的语句用来创建按钮,传递给构造函数的字符串参数指明了按钮上的标签:参数指明了按钮上的标签: Button enter = new Button ( 操作操作);(2) 常用方法常用方法 调用按钮的调用按钮的getLabel( )方法可以返回按钮标签字符串;方法可以返回按钮标签字符串;调用按钮的调用按钮的s

75、etLabel(String s)方法可以把按钮的标方法可以把按钮的标签设置为字符串签设置为字符串s。(3) 产生事件产生事件按钮可以引发动作事件,当用户单击一个按钮时就引按钮可以引发动作事件,当用户单击一个按钮时就引发了一个动作事件,希望响应按钮引发的动作事件发了一个动作事件,希望响应按钮引发的动作事件的程序必须把按钮注册给实现了的程序必须把按钮注册给实现了ActionListener接接口的动作事件监听者,同时,为这个接口的口的动作事件监听者,同时,为这个接口的actionPerformed(ActionEvent e)方法书写方法体。方法书写方法体。在方法体中,可以调用在方法体中,可以调

76、用e.getSource( )方法来获取引方法来获取引发动作事件的按钮对象引用,也可以调用发动作事件的按钮对象引用,也可以调用e.getActionCommand( )方法来获取按钮的标签或事先为这个按钮设置的方法来获取按钮的标签或事先为这个按钮设置的命令名。命令名。 例例 7-6 BtnLabelAction.java1: import java.applet.*;2: import java.awt.*;3: import java.awt.event.*;4:5: public class BtnLabelAction extends Applet implements ActionLi

77、stener6: 7: Label prompt;8: Button btn;9: public void init( )10: 11: prompt = new Label(你好你好);12: btn = new Button(操作操作);13: add(prompt);14: add(btn);15: btn.addActionListener(this);16: 17: public void actionPerformed(ActionEvent e)18: 19: if(e.getSource( )=btn)20: if(prompt.getText( )=你好你好)21: prom

78、pt.setText(再见再见);22: else23: prompt.setText(你好你好);24: 25: 例例7-6中中的的Applet程程序序包包括括一一个个标标签签对对象象prompt和和一一个个 按按 钮钮 对对 象象 btn。 第第 5句句 声声 明明 该该 类类 将将 实实 现现ActionListener接接口口,是是ActionEvent事事件件的的监监听听者者。第第15句句将将按按钮钮对对象象btn注注册册给给这这个个监监听听者者,这这样样它它将将 监监 听听 并并 处处 理理 btn引引 发发 的的 动动 作作 事事 件件 。 第第 17到到 24句句 的的 act

79、ionPerormed( )方方法法在在用用户户单单击击btn时时被被系系统统自自动动调调用用。第第19句句判判断断动动作作事事件件是是否否是是由由按按钮钮btn引引发发的的,是是则则修修改改prompt对象的文本标签。图对象的文本标签。图 7.8为例为例7-6的运行结果。的运行结果。 图图 7.8 例例7-6的运行结果的运行结果3. 动作事件动作事件(ActionEvent)ActionEvent类只包含一个事件,即执行动作事件类只包含一个事件,即执行动作事件ACTION-PERFORMED。ACTION-PERFORMED是引发某个动作执行的事件。是引发某个动作执行的事件。能够触发这个事件

80、的动作包括:能够触发这个事件的动作包括:(1) 点击按钮;点击按钮;(2) 双击一个列表中的选项;双击一个列表中的选项;(3) 选择菜单项;选择菜单项;(4) 在文本框中输入回车。在文本框中输入回车。ActionEvent类的重要方法有:类的重要方法有:(1) public String getActionCommand( )这个方法返回引发事件的动作的命令名,这个命令名这个方法返回引发事件的动作的命令名,这个命令名可以通过调用可以通过调用setActionCommand( )方法指定给事方法指定给事件源组件,也可以使用事件源的缺省命令名。例如件源组件,也可以使用事件源的缺省命令名。例如一个按

81、钮组件一个按钮组件m-Button是是ACTION-PERFORMED事件的事件源,下面的语句将这个按钮对象的动作事件的事件源,下面的语句将这个按钮对象的动作命令名设为命令名设为“命令名命令名”并将它注册给当前的监听者:并将它注册给当前的监听者: Button m-Button = new Button(按钮标签按钮标签); m-Button.setActionCommand(命令名命令名); m-Button.addActionListener(this); 动作事件的监听者需要实现动作,监听者接口的方法动作事件的监听者需要实现动作,监听者接口的方法为:为:public void actio

82、nPerformed(ActionEvent e)if ( e.getActionCommand( ) = 命令名命令名 ) 这里注意这里注意setActionCommand( )方法与方法与getActionCommand( )方法属于不同的类,方法属于不同的类,getActionCommand( )方法方法是是ActionEvent类的方法,而类的方法,而setActionCommand( )方法是其上发生动作事件的事件源,如按钮、菜单方法是其上发生动作事件的事件源,如按钮、菜单项等的方法。事件源对象也可以不专门调用项等的方法。事件源对象也可以不专门调用setActionCommand(

83、)方法来指定命令名,此时方法来指定命令名,此时getActionCommand( )方法返回缺省的命令名,例如上面的程序片断如果方法返回缺省的命令名,例如上面的程序片断如果去掉设置动作命令名的一句,则监听者接口的方法去掉设置动作命令名的一句,则监听者接口的方法可以写为:可以写为:public void actionPerformed(ActionEvent e)if ( e.getActionCommand( ) = 按钮标签按钮标签 ) 可可 见见 按按 钮钮 的的 缺缺 省省 命命 令令 名名 就就 是是 按按 钮钮 的的 标标 签签 。 使使 用用 getActionCommand( )

84、方方 法法 可可 以以 区区 分分 产产 生生 动动 作作 命命 令令 的的 不不 同同 事事 件件 源源 , 使使 actionPerformed( )方方法法对对不不同同事事件件源源引引发发的的事事件件区区分分对对待待处处理理(区区分分事事件件的的事事件件源源也也可可以以使使用用getSource( )方方法法,但但是是这这样样一一来来处处理理事事件件的的代代码码就就与与GUI结结合合得得过过于于紧紧密密,对于小程序尚可接受,对于大程序则不提倡对于小程序尚可接受,对于大程序则不提倡)。 (2) public int getModifiers( )如果发生动作事件的同时用户还按了如果发生动作

85、事件的同时用户还按了Ctrl、Shift等功等功能键,则可以调用这个事件的能键,则可以调用这个事件的getModifiers( )方法方法来获得和区分这些功能键,实际上就是把一个动作来获得和区分这些功能键,实际上就是把一个动作事件再细分成几个事件;把一个命令细分成几个命事件再细分成几个事件;把一个命令细分成几个命令。将令。将getModifiers( )方法的返回值与方法的返回值与ActionEvent类的几个静态常量类的几个静态常量ALT-MASK,CTRL-MASK,SHIFT-MASK,META-MASK相比较,就可以判相比较,就可以判断用户按下了哪个功能键。断用户按下了哪个功能键。7.

86、6 文本框、文本区域与文本事件文本框、文本区域与文本事件 1. 文本事件文本事件(TextEvent)TextEvent类只包含一个事件,即代表文本区域中文类只包含一个事件,即代表文本区域中文本变化的事件本变化的事件TEXT-VALUE-CHANGED,在文本,在文本区域中改变文本内容。例如,删除字符、键入字符区域中改变文本内容。例如,删除字符、键入字符都将引发这个事件。这个事件比较简单,不需要特都将引发这个事件。这个事件比较简单,不需要特别判断事件类型的方法和常量。别判断事件类型的方法和常量。2. 文本框与文本域文本框与文本域(TextField与与TextArea)Java中用于文本处理的

87、基本组件有两种:单行文本框中用于文本处理的基本组件有两种:单行文本框TextField和多行文本区域和多行文本区域TextArea,它们都是,它们都是TextComponent的子类。的子类。(1) 创建创建在创建文本组件的同时可以指出文本组件中的初始文在创建文本组件的同时可以指出文本组件中的初始文本字符串,如下面的语句创建了一个本字符串,如下面的语句创建了一个10行行45列的多列的多行文本区域:行文本区域:TextArea textArea1 = new TextArea(10,45);而创建能容纳而创建能容纳8个字符,初始字符串为个字符,初始字符串为“卡号卡号”的单的单行文本框可以使用如下

88、的语句:行文本框可以使用如下的语句:TextField name = new TextField(卡号卡号,8); (2) 常用方法常用方法先介绍先介绍TextComponent中的常用方法,即中的常用方法,即TextField和和TextArea都拥有的常用方法。都拥有的常用方法。用用户户可可以以在在已已创创建建好好的的文文本本区区域域中中自自由由输输入入和和编编辑辑文文本本 信信 息息 , 对对 于于 用用 户户 输输 入入 的的 信信 息息 , 可可 以以 调调 用用TextComponent的的getText( )方方法法来来获获得得,这这个个方方法法的的返返回回值值为为一一个个字字符

89、符串串。如如果果希希望望在在程程序序中中对对文文本本区区域域显显示示的的内内容容赋赋值值,可可以以调调用用TextComponent的的另一个方法另一个方法setText( )。例如下面的语句:。例如下面的语句:textArea1.setText(你好,欢迎!你好,欢迎!);将文本区域的内容置为将文本区域的内容置为“你好,欢迎!你好,欢迎!”。某某些些情情况况下下需需要要将将文文本本区区域域设设为为不不能能编编辑辑的的。例例如如,电电话话卡卡的的卡卡号号是是系系统统自自动动生生成成的的,不不需需要要也也不不允允许许用用户户随随意意改改动动,这这时时可可以以用用如如下下的的语语句句使使对对应应电

90、电话话卡卡号的文本框卡卡号的文本框cardNo不可被用户通过界面改动:不可被用户通过界面改动:cardNo.setEditable(false);另另外外,可可以以使使用用isEditable( )方方法法判判断断当当前前的的文文本本区区域是否可以被编辑。域是否可以被编辑。TextComponent中中还还有有一一些些用用来来指指定定或或获获得得文文本本区区域域中中“选选定定状状态态”文文本本的的方方法法,选选定定状状态态的的文文本本一一般般用用高高亮亮或或反反白白显显示示,select(int start, int end)方方法法将将根根据据指指定定的的起起止止位位置置选选定定一一段段文文

91、本本;selectAll( )方方法法将将选选定定文文本本区区域域中中的的所所有有文文本本;setSelectionStart( )方方法法和和setSelectionEnd( )方方法法分分别别指指定定选选定定文文本本的的 起起 、 止止 位位 置置 ; 如如 果果 文文 本本 区区 域域 中中 已已 经经 有有 选选 定定 文文 本本 , getSelectionStart( )方方法法和和getSelectionEnd( )方方法法将将获获得得选选定定文文本本的的起起、止止位位置置;如如果果希希望望获获得得选选定定文文本本的的具具体体内内容容,可可以以调调用用getSelectedTex

92、t( )方方法法,这这个个方方法法返返回回一一个字符串。个字符串。除了继承除了继承TextComponent类的方法,类的方法,TextField还定义还定义了一些自己的特殊方法,例如某些场合下了一些自己的特殊方法,例如某些场合下(如输入如输入密码时密码时)希望文本区域中的内容不如实回显在屏幕希望文本区域中的内容不如实回显在屏幕上,可以调用如下的方法:上,可以调用如下的方法:TextField tf = new TextField(输入密码输入密码);tf.setEchoChar(*);这样一来,这样一来,TextField中的每个字符中的每个字符(无论中西文无论中西文)都被都被回显成一个星号

93、回显成一个星号*,保证看不到其中的实际字符。,保证看不到其中的实际字符。另外,另外,TextField还定义了还定义了echoCharIsSet( )方法确认方法确认当前文本框是否处于不回显状态;当前文本框是否处于不回显状态;getEchoChar( )方法获得当前文本框不回显的屏蔽字符。方法获得当前文本框不回显的屏蔽字符。除除了了继继承承TextComponent类类的的方方法法,TextArea也也定定义义了了两两个个特特殊殊的的方方法法append(String s)和和insert(String s, int index)。append(String s)方方法法在在当当前前文文本本区

94、区域域已已有有文文本本的的后后面面添添加加字字符符串串参参数数s指指定定的的文文本本内内容容;insert(String s, int index)方方法法将将字字符符串串s插插入入到到已已有有文本的指定序号处。文本的指定序号处。(3) 事件响应事件响应TextField和和TextArea的事件响应首先由它们的父类的事件响应首先由它们的父类TextComponent决定,所以先讨论决定,所以先讨论TextComponent的事件响应。的事件响应。TextComponent可以引发一种事件:可以引发一种事件:当用户修改文本区域中的文本,如做文本的添加、当用户修改文本区域中的文本,如做文本的添加

95、、删除、修改等操作时,将引发删除、修改等操作时,将引发TextEvent对象代表对象代表的文本改变事件。在此基础上的文本改变事件。在此基础上TextField还比还比TextArea多产生一种事件,当用户在文本框中按回多产生一种事件,当用户在文本框中按回车键时,将引发代表动作事件的车键时,将引发代表动作事件的ActionEvent事件,事件,TextArea却不能产生却不能产生ActionEvent事件,也没有事件,也没有addActionListener( )这个方法。这个方法。如果希望响应上述两类事件,则需要把文本框加入实如果希望响应上述两类事件,则需要把文本框加入实现了现了TextLis

96、tener接口的文本改变事件监听者和实接口的文本改变事件监听者和实现了现了ActionListener接口的动作事件监听者:接口的动作事件监听者: textField1.addTextListener(this); textField1.addActionListener(this);在监听者内部分别定义响应文本改变事件和动作事件在监听者内部分别定义响应文本改变事件和动作事件的方法:的方法: public void textValueChanged(TextEvent e); public void actionPerformed(ActionEvent e);就可以响应文本框引发的文本改变事

97、件和动作事件。就可以响应文本框引发的文本改变事件和动作事件。对对于于文文本本改改变变事事件件,调调用用方方法法e.getSource( )可可以以获获得得引引发发该该事事件件的的文文本本框框的的对对象象引引用用。调调用用这这个个文文本本框框的方法,可以获得改变后的文本内容:的方法,可以获得改变后的文本内容:String afterChange = (TextField)e.getSource( ).getText( );对对于于动动作作事事件件,同同样样可可以以通通过过调调用用e.getSource( )方方法法获得用户输入回车的那个文本框的对象引用。获得用户输入回车的那个文本框的对象引用。例

98、例 7-7 TextComponentEvent.java 1: import java.applet.*;2: import java.awt.*;3: import java.awt.event.*;4:5: public class TextComponentEvent extends Applet 6: implements TextListener,ActionListener7: 8: TextField tf;9: TextArea ta;10: public void init( )11: 12: tf = new TextField(45);13: ta = new Text

99、Area(10,45);14: add(tf);15: add(ta);16: tf.addActionListener(this);17: tf.addTextListener(this);18: 19: public void textValueChanged(TextEvent e)20: 21: if(e.getSource( )=tf)22: ta.setText(TextField)e.getSource( ).getText( );23: 24: public void actionPerformed(ActionEvent e)25: 26: if(e.getSource( )

100、=tf)27: ta.setText();28: 29: 图图7.9是是例例7-7的的运运行行结结果果。例例7-7的的Applet程程序序包包含含一一个个TextField对对象象tf和和一一个个TextArea对对象象ta,这这个个类类实实现现了了TextListener接接口口和和ActionListener接接口口,是是文文本本事事件件和和动动作作事事件件的的监监听听者者。第第16和和17句句将将tf对对象象 分分 别别 注注 册册 给给 这这 两两 个个 监监 听听 者者 。 第第 19到到 23句句 定定 义义 的的 textValueChanged( )方方法法用用来来处处理理文文

101、本本事事件件,当当用用户户在在tf中中输输入入或或修修改改文文本本时时,在在tf文文本本区区域域中中可可以以得得到到一一个个同同步步的的拷拷贝贝。第第24到到28句句定定义义的的actionPerformed( )方方法法用用来来处处理理动动作作事事件件,当当用用户户在在tf中中输输入入回回车车时时将将tf中中的的文本清空。文本清空。图图 7.9 例例7-7的运行结果的运行结果 在在以以上上的的例例子子里里,监监听听者者是是包包容容组组件件的的容容器器,实实际际上上监监听听者者完完全全可可以以是是另另外外的的对对象象。另另外外,同同一一个个事事件件源源的的两两个个不不同同性性质质的的监监听听者

102、者可可以以在在一一个个类类上上实实现现,也也可可以以分分成成两两个个独独立立的的类类实实现现,成成为为两两个个独独立立的的各各负责一种事件的监听者。负责一种事件的监听者。7.7 单、复选按钮,列表与选择事件单、复选按钮,列表与选择事件 1. 选择事件选择事件(ItemEvent)ItemEvent类只包含一个事件,即代表选择项的选中类只包含一个事件,即代表选择项的选中状态发生变化的事件状态发生变化的事件ITEM-STATE-CHANGED。引发这类事件的动作包括:引发这类事件的动作包括:(1) 改变列表类改变列表类List对象选项的选中或不选中状态。对象选项的选中或不选中状态。(2) 改变下拉

103、列表类改变下拉列表类Choice对象选项的选中或不选中对象选项的选中或不选中状态。状态。(3) 改变复选按钮类改变复选按钮类Checkbox对象的选中或不选中状对象的选中或不选中状态。态。(4) 改变检测盒菜单项改变检测盒菜单项CheckboxMenuItem对象的选对象的选中或不选中状态。中或不选中状态。ItmeEvent类的主要方法有:类的主要方法有:(1) public ItemSelectable getItemSelectable( )此方法返回引发选中状态变化事件的事件源,例如,此方法返回引发选中状态变化事件的事件源,例如,选项变化的选项变化的List对象或选中状态变化的对象或选中

104、状态变化的Checkbox对对象,这些能引发选中状态变化事件的都是实现了象,这些能引发选中状态变化事件的都是实现了ItemSelectable接口的类的对象,包括接口的类的对象,包括List对象、对象、Choice对象、对象、Checkbox对象等。对象等。getItemSelectable( )方法返回的就是这些类的对象引用。方法返回的就是这些类的对象引用。(2) public Object getItem( )此方法返回引发选中状态变化事件的具体选择项,例此方法返回引发选中状态变化事件的具体选择项,例如用户选中的如用户选中的Choice中的具体中的具体item,通过调用这个,通过调用这个方

105、法可以知道用户选中了哪个选项。方法可以知道用户选中了哪个选项。(3) public int getStateChange( )此方法返回具体的选中状态变化类型,它的返回值在此方法返回具体的选中状态变化类型,它的返回值在ItemEvent类的几个静态常量列举的集合之内:类的几个静态常量列举的集合之内: ItemEvent.SELECTED: 代表选项被选中。代表选项被选中。 ItemEvent.DESELECTED: 代表选项被放弃不选。代表选项被放弃不选。2. 复选按钮复选按钮(Checkbox)(1) 创建创建复选按钮又称为检测盒,用复选按钮又称为检测盒,用Checkbox类的对象表示。类的

106、对象表示。创建复选按钮对象时可以同时指明其文本说明标签,创建复选按钮对象时可以同时指明其文本说明标签,这个文本标签简要地说明了检测盒的意义和作用。这个文本标签简要地说明了检测盒的意义和作用。Checkbox backg = new Checkbox(背景色背景色);(2) 常用方法常用方法每个复选按钮都只有两种状态:被用户选中的每个复选按钮都只有两种状态:被用户选中的check状态,未被用户选中的状态,未被用户选中的uncheck状态,任何时刻复状态,任何时刻复选按钮都只能处于这两种状态之一。查看用户是否选按钮都只能处于这两种状态之一。查看用户是否点击选择了复选按钮,可以调用点击选择了复选按钮

107、,可以调用Checkbox的方法的方法getState( ),这个方法的返回值为布尔量。若复选按钮被选,这个方法的返回值为布尔量。若复选按钮被选中,则返回中,则返回true,否则返回,否则返回false。调用。调用Checkbox的的另一个方法另一个方法setState( )可以用程序设置是否选中复选可以用程序设置是否选中复选按钮。例如下面的语句将使按钮。例如下面的语句将使Checkbox处于选中的处于选中的状态。状态。 backg.setState( true ); (3) 事件响应事件响应当用户点击检测盒使其选中状态发生变化时就会引发当用户点击检测盒使其选中状态发生变化时就会引发ItemE

108、vent类代表的选择事件。如果这个检测盒已经用类代表的选择事件。如果这个检测盒已经用如下的语句:如下的语句: backg.addItemListener(this);把自身注册给把自身注册给ItemEvent事件的监听者事件的监听者ItemListener。则系统会自动调用这个则系统会自动调用这个ItemListener中的方法:中的方法: public void itemStateChanged(ItemEvent e) 响应复选按钮的状态改变。响应复选按钮的状态改变。所所以以实实际际实实现现了了ItemListener接接口口的的监监听听者者,例例如如包包容容复复选选按按钮钮的的容容器器,

109、需需要要具具体体实实现现这这个个方方法法。这这个个方方法法的的方方法法体体通通常常包包括括这这样样的的语语句句:调调用用选选择择事事件件的的方方法法e.getItemSelectable( )获获得得引引发发选选择择事事件件的的事事件件源源对对象象引引用用,再再调调用用e.getState( )获获取取选选择择事事件件之之后后的的状状态态。也也可可以以直直接接利利用用事事件件源源对对象象自自身身的的方方法法进进行行操操作作。需需要要注注意意的的是是:getItemSelectable( )方方法法的的返返回回值值是是实实现现了了Selectable接接口口的的对对象象,需需要要把它强制转化成真

110、正的事件源对象类型。例如:把它强制转化成真正的事件源对象类型。例如:(Checkbox)e.getItemSelectable( ).getState( );(Checkbox)e.getItemSelectable( ).setState(false); 总的来说,需要响应复选按钮事件的情况不多,通常总的来说,需要响应复选按钮事件的情况不多,通常只需要知道一个确切的时刻。例如用户单击某个按只需要知道一个确切的时刻。例如用户单击某个按钮的时刻、复选按钮所处的最终状态等。这可以通钮的时刻、复选按钮所处的最终状态等。这可以通过调用复选按钮自身的方法很方便地获得。过调用复选按钮自身的方法很方便地获得

111、。例例 7-8 TextCheckbox.java 1: import java.applet.*;2: import java.awt.*;3: import java.awt.event.*;4:5: public class TestCheckbox extends Applet implements ItemListener6: 7: Checkbox ckb;8: Button btn;9: public void init( )10: 11: ckb = new Checkbox(背景色背景色);12: btn = new Button(效果效果);13: add(ckb);14:

112、 add(btn);15: ckb.addItemListener(this);16: 17: public void itemStateChanged(ItemEvent e)18: 19: Checkbox temp;20: if(e.getItemSelectable( ) instanceof Checkbox)21: 22: temp = (Checkbox)(e.getItemSelectable( );23: if(temp.getLabel( )=背景色背景色)24: if(temp.getState( )25: btn.setBackground(Color.cyan);26

113、: else27: btn.setBackground(Color.gray);28: 29: 30: 图图7.10是例是例7-8的运行结果。的运行结果。 图图 7.10 例例7-8的运行结果的运行结果 例例7-8的程序定义了一个实现了的程序定义了一个实现了ItemListener接口的接口的Applet,其中包括一个复选按钮和一个按钮。第,其中包括一个复选按钮和一个按钮。第11句创建的复选按钮的标签为句创建的复选按钮的标签为“背景色背景色”,第,第15句把句把它注册给选择事件的监听者。第它注册给选择事件的监听者。第17句到第句到第29句定义句定义的的itemStateChanged( )方法

114、用来具体处理所监听到方法用来具体处理所监听到的选择事件,第的选择事件,第20句检查引发选择事件的事件源是句检查引发选择事件的事件源是否是一个否是一个Checkbox对象,是则把这个事件源的引对象,是则把这个事件源的引用赋值给对象用赋值给对象temp。第。第23句检查这个复选按钮是否句检查这个复选按钮是否是标签为是标签为“背景色背景色”的复选按钮,第的复选按钮,第24到第到第27句利句利用一个用一个if/else结构根据复选按钮是否选中的状态设结构根据复选按钮是否选中的状态设置按钮置按钮btn的背景色。的背景色。3. 单选按钮组单选按钮组(CheckboxGroup)(1) 创建创建Checkb

115、ox只能提供只能提供“二选一二选一”的机制。要想实现的机制。要想实现“多选一多选一”,可以选择单选按钮组。单选按钮组是一,可以选择单选按钮组。单选按钮组是一组组Checkbox的集合,用的集合,用CheckboxGroup类的对象类的对象表示。每个表示。每个Checkbox对应一种可能的取值情况,对应一种可能的取值情况,例如,下面语句创建的单选按钮组代表了三种字体例如,下面语句创建的单选按钮组代表了三种字体风格。风格。style = new CheckboxGroup( );p = new Checkbox(普通普通,true,style);b = new Checkbox(黑体黑体,fals

116、e,style);i = new Checkbox(斜体斜体,false,style); 把把CheckboxGroup加入容器时需要把其中的每个单加入容器时需要把其中的每个单选按钮逐个加入到容器中,而不能使用选按钮逐个加入到容器中,而不能使用CheckboxGroup对象一次性地加入。例如,加入上对象一次性地加入。例如,加入上面的单选按钮需引用如下的语句:面的单选按钮需引用如下的语句: add(p); add(b); add(i); (2) 常用方法常用方法单选按钮的选择是互斥的,即当用户选中了组中的一单选按钮的选择是互斥的,即当用户选中了组中的一个按钮后,其他按钮将自动处于未选中状态。调用

117、个按钮后,其他按钮将自动处于未选中状态。调用CheckboxGroup的的getSelectedCheckbox( )方法可以方法可以获知用户选择了哪个按钮,这个方法返回用户选中获知用户选择了哪个按钮,这个方法返回用户选中的的Checkbox对象,再调用该对象的方法对象,再调用该对象的方法getLabel( )就可以知道用户选择了什么信息。同样,通过调用就可以知道用户选择了什么信息。同样,通过调用CheckboxGroup的的setSelectedCheckbox( )方法,可方法,可以在程序中指定单选按钮组中的那个按钮。例如,以在程序中指定单选按钮组中的那个按钮。例如,下面的语句说明字体的风

118、格为斜体。下面的语句说明字体的风格为斜体。 sex.setSelectedCheckbox( i );另外,也可以直接使用按钮组中的另外,也可以直接使用按钮组中的Checkbox单选按单选按钮的方法。例如直接调用钮的方法。例如直接调用 i.getState( );就可以知道这个按钮是否被选中。如果这个按钮被就可以知道这个按钮是否被选中。如果这个按钮被选中了,那么其他按钮一定处于未选中状态。单选选中了,那么其他按钮一定处于未选中状态。单选按钮组中可以包括两个或更多的单选按钮。按钮组中可以包括两个或更多的单选按钮。(3) 事件响应事件响应CheckboxGroup类不是类不是java.awt.*包

119、中的类,它是包中的类,它是Object的直接子类,所以按钮组不能响应事件,但的直接子类,所以按钮组不能响应事件,但是按钮组中的每个按钮可以响应是按钮组中的每个按钮可以响应ItemEvent类的事类的事件。由于单选按钮组中的每个单选按钮都是件。由于单选按钮组中的每个单选按钮都是Checkbox对象,它们对事件的响应与检测盒对事对象,它们对事件的响应与检测盒对事件的响应相同。件的响应相同。 例例 7-9 TestCheckboxgroup1: import java.applet.*;2: import java.awt.*;3: import java.awt.event.*;4:5: publ

120、ic class TestCheckboxgroup extends Applet implements ItemListener6: 7: CheckboxGroup style;8: Checkbox p,b,i;9: Button btn;10: public void init( )11: 12: style = new CheckboxGroup( );13: p = new Checkbox(普通普通,true,style);14: b = new Checkbox(黑体黑体,false,style);15: i = new Checkbox(斜体斜体,false,style);1

121、6: btn = new Button(效果效果);17: add(p);18: add(b);19: add(i);20: add(btn);21: p.addItemListener(this);22: b.addItemListener(this);23: i.addItemListener(this);24: 25: public void itemStateChanged(ItemEvent e)26: 27: Checkbox temp;28: Font oldF = btn.getFont( );29: if(e.getItemSelectable( ) instanceof C

122、heckbox)30: 31: temp = (Checkbox)(e.getItemSelectable( );32: if(temp.getLabel( )=普通普通)33: btn.setFont(new Font(oldF.getName( ),Font.PLAIN,oldF.getSize( );34: if(temp.getLabel( )=黑体黑体)35: btn.setFont(new Font(oldF.getName( ),Font.BOLD,oldF.getSize( );36: if(temp.getLabel( )=斜体斜体)37: btn.setFont(new F

123、ont(oldF.getName( ),Font.ITALIC,oldF.getSize( );38: 39: 40: 图图7.11是例是例7-9的运行结果。的运行结果。 图图 7.11 例例7-9的运行结果的运行结果 例例7-9中的程序定义了一个实现了中的程序定义了一个实现了ItemListener接口的接口的Applet,其中包含一个单选按钮组,其中包含一个单选按钮组CheckboxGroup、若干个单选按钮对象和一个若干个单选按钮对象和一个Button。第。第12句创建的句创建的单选按钮组对象单选按钮组对象style用来辅助用户输入字体的不同用来辅助用户输入字体的不同风格。第风格。第13

124、到到15句创建的单选按钮对象分别代表句创建的单选按钮对象分别代表“普通普通”、“黑体黑体”、“斜体斜体”三种字体风格。第三种字体风格。第17到到19句将这三个对象按钮加入到句将这三个对象按钮加入到style单选按钮组中。单选按钮组中。单选按钮组中的各个单选按钮之间是互斥的,选中单选按钮组中的各个单选按钮之间是互斥的,选中了其中的某一个,其他的按钮就自动处于不选中的了其中的某一个,其他的按钮就自动处于不选中的状态。状态。第第21到到23句把这三个单选按钮注册给实现了句把这三个单选按钮注册给实现了ItemListener接口的监听者。第接口的监听者。第25到到39句定义的句定义的itemState

125、Changed( )方法用来处理选择事件。它首先在第方法用来处理选择事件。它首先在第29句判断引句判断引发选择事件的事件源是否是单选按钮组,然后查看发选择事件的事件源是否是单选按钮组,然后查看组中各单选按钮的选中状态。若选中,则将按钮的组中各单选按钮的选中状态。若选中,则将按钮的字体设置为这个单选按钮指定的字体风格。字体设置为这个单选按钮指定的字体风格。4. Choice(下拉列表下拉列表)(1) 创建创建下拉列表也是下拉列表也是“多选一多选一”的输入界面。与单选按钮组的输入界面。与单选按钮组利用单选按钮把所有选项列出的方法不同,下拉列利用单选按钮把所有选项列出的方法不同,下拉列表的所有选项被

126、折叠收藏起来,只显示最前面的或表的所有选项被折叠收藏起来,只显示最前面的或被用户选中的一个。如果希望看到其他的选项,只被用户选中的一个。如果希望看到其他的选项,只需单击下拉列表右边的下三角按钮就可以需单击下拉列表右边的下三角按钮就可以“下拉下拉”出一个罗列了所有选项的长方形区域。出一个罗列了所有选项的长方形区域。创建下拉列表包括创建和添加选项两个步骤。创建下拉列表包括创建和添加选项两个步骤。 Choice size = new Choice( ); /创建下拉列表创建下拉列表 size.add(10); /为下拉列表加入选项为下拉列表加入选项 size.add(14); size.add(18

127、); (2) 常用方法常用方法下拉列表的常用方法包括获得选中选项的方法、设置下拉列表的常用方法包括获得选中选项的方法、设置选中选项的方法、添加和去除下拉列表选项的方法。选中选项的方法、添加和去除下拉列表选项的方法。getSelectedIndex( )方法将返回被选中的选项的序号方法将返回被选中的选项的序号(下拉列表中第一个选项的序号为下拉列表中第一个选项的序号为0,第二个选项的,第二个选项的序号为序号为1,依此类推,依此类推)。getSelectedItem( )方法将返方法将返回被选中选项的标签文本字符串。回被选中选项的标签文本字符串。select(int index)方法和方法和sele

128、ct(String item)方法使程序选中指定序号方法使程序选中指定序号或文本内容的选项。或文本内容的选项。add(String item)方法和方法和insert(String item, int index)方法分别将新选项方法分别将新选项item加在当前下拉列表的最后或指定的序号处。加在当前下拉列表的最后或指定的序号处。 remove(int index)方法和方法和remove(String item)方法把方法把指定序号或指定标签文本的选项从下拉列表中删除。指定序号或指定标签文本的选项从下拉列表中删除。removeAll( )方法将把下拉列表中的所有选项删除。方法将把下拉列表中的所

129、有选项删除。(3) 事件响应事件响应下拉列表可产生下拉列表可产生ItemEvent代表的选择事件。如果把代表的选择事件。如果把选项注册给实现了接口选项注册给实现了接口ItemListener的监听者:的监听者:size.addItemListener( );则当用户单击下拉列表的某个选项做出选择时,系统则当用户单击下拉列表的某个选项做出选择时,系统自动产生一个自动产生一个ItemEvent类的对象包含这个事件的类的对象包含这个事件的有关信息,并把该对象作为实际参数传递给被自动有关信息,并把该对象作为实际参数传递给被自动调用的监听者的选择事件响应方法。调用的监听者的选择事件响应方法。public

130、 void itemStateChanged(ItemEvent e); 在这个方法里,调用在这个方法里,调用e.getItemSelectable( )就可以获就可以获得引发当前选择事件的下拉列表事件源,再调用此得引发当前选择事件的下拉列表事件源,再调用此下拉列表的有关方法,就可以得知用户具体选择了下拉列表的有关方法,就可以得知用户具体选择了哪个选项。哪个选项。String selectedItem = (Choice)e.getItemSelectable( ).getSelectedItem( );这里对这里对e.getItemSelectable( )方法的返回值进行了强方法的返回值进

131、行了强制类型转换,转换成制类型转换,转换成Choice类的对象引用后方可调类的对象引用后方可调用用Choice类的方法。类的方法。例例 7-10 TestChoice.java1: import java.applet.*;2: import java.awt.*;3: import java.awt.event.*;4:5: public class TestChoice extends Applet implements ItemListener6: 7: Choice size;8: Button btn;9: public void init( ) 10: 11: size = new

132、 Choice( );12: size.add(10);13: size.add(14);14: size.add(18);15: add(size);16: btn = new Button(效果效果);17: add(btn);18: size.addItemListener(this);19: 20: public void itemStateChanged(ItemEvent e)21: 22: Choice temp;23: Font oldF;24: String s;25: int si;26: if(e.getItemSelectable( ) instanceof Choic

133、e)27: 28: oldF = btn.getFont( );29: temp = (Choice)(e.getItemSelectable( );30: s = temp.getSelectedItem( );31: si = Integer.parseInt(s);32: btn.setFont(new Font(oldF.getName( ),oldF.getStyle( ),si);33: 34: 35: 图图7.12是例是例7-10的运行结果。例的运行结果。例7-10的程序定义了一的程序定义了一个实现了个实现了ItemListener接口的接口的Applet,它包含一个,它包含一个

134、Choice对象对象size和一个按钮和一个按钮btn。第。第11句创建句创建Choice对象。第对象。第12到第到第14句把句把“10”,“14”,“18”三三个字符串项目加入下拉列表个字符串项目加入下拉列表size中。第中。第18句把下拉句把下拉列表对象列表对象size注册给实现了注册给实现了ItemListener接口的监听接口的监听者者Applet。第。第20到第到第34句的处理选择事件的方法句的处理选择事件的方法itemStateChanged( )中。第中。第26句首先判断引发选择事件的事件源是否句首先判断引发选择事件的事件源是否是下拉列表对象。第是下拉列表对象。第29句把这个事件

135、源强制类型转句把这个事件源强制类型转换成换成Choice对象。第对象。第30句获得事件源句获得事件源Choice被用户被用户选中的项目字符串,第选中的项目字符串,第31句把这个字符串转换成整句把这个字符串转换成整数。第数。第32句将句将btn的字体设置成的字体设置成size中用户指定的字中用户指定的字体大小。体大小。图图 7.12 例例7-10的运行结果的运行结果 需要响应下拉列表引发的选择事件的场合不多,因为需要响应下拉列表引发的选择事件的场合不多,因为通常的界面都应该给用户改变选择并最终确认选择通常的界面都应该给用户改变选择并最终确认选择的机会,如果用户刚选择某个选项就把程序调入相的机会,

136、如果用户刚选择某个选项就把程序调入相应的分支,将剥夺用户改变选择的权利,用起来不应的分支,将剥夺用户改变选择的权利,用起来不十分方便。所以通常都设一个接受用户确认命令的十分方便。所以通常都设一个接受用户确认命令的按钮,如按钮,如“输入输入”按钮,当用户单击该按钮时,说按钮,当用户单击该按钮时,说明他明他/她已经做出了提交前的最终选择,此时读取她已经做出了提交前的最终选择,此时读取下拉列表和其他组件中的选项最为合适。下拉列表和其他组件中的选项最为合适。5. List(列表列表)(1) 创建创建列表也是列出一系列的选择项供用户选择,但是列表列表也是列出一系列的选择项供用户选择,但是列表可以实现可以

137、实现“多选多多选多”,即允许复选。在创建列表时,即允许复选。在创建列表时,同样应该将它的各项选择项同样应该将它的各项选择项(称为列表项称为列表项Item)加入加入到列表中去,如下面的语句:到列表中去,如下面的语句:MyList = new List(4,true);MyList.add(北京北京);MyList.add(上海上海); 将创建一个包括两个地址选项的列表,将创建一个包括两个地址选项的列表,List对象的构对象的构造函数的第一个参数表明列表的高度,可以一次同造函数的第一个参数表明列表的高度,可以一次同时显示几个选项,第二个参数表明列表是否允许复时显示几个选项,第二个参数表明列表是否允

138、许复选,即同时选中多个选项。选,即同时选中多个选项。(2) 常用方法常用方法如果想获知用户选择了列表中的哪个选项,可以调用如果想获知用户选择了列表中的哪个选项,可以调用List对象的对象的getSelectedItem( )方法,这个方法返回方法,这个方法返回用户选中的选择项文本。与单选按钮不同的是,列用户选中的选择项文本。与单选按钮不同的是,列表中可以有复选和多选,所以表中可以有复选和多选,所以List对象还有一个方对象还有一个方法法getSelectedItems( )方法,该方法返回一个方法,该方法返回一个String类型的数组,里面的每个元素是一个被用户选中的类型的数组,里面的每个元素

139、是一个被用户选中的选择项,所有的元素包括了所有被用户选中的选项。选择项,所有的元素包括了所有被用户选中的选项。除了可以直接返回被选中的选项的标签字符串,还可除了可以直接返回被选中的选项的标签字符串,还可以获得被选中选项的序号。在以获得被选中选项的序号。在List里面,第一个加里面,第一个加入入List的选项的序号是的选项的序号是0,第二个是,第二个是1,依此类推。,依此类推。getSelectedIndex( )方法将返回被选中的选项的序号,方法将返回被选中的选项的序号,getSelectedIndexs( )方法将返回由所有被选中的选项的序号组成的整方法将返回由所有被选中的选项的序号组成的整

140、型数组。型数组。select(int index)和和deselect(int index)方法可以使指定方法可以使指定序号处的选项被选中或不选中;序号处的选项被选中或不选中;add(String item)方方法和法和add(String item, int index)方法分别将标签为方法分别将标签为item的选项加入列表的最后面或加入列表的指定序的选项加入列表的最后面或加入列表的指定序号处;号处;remove(String item)方法和方法和remove(int index)方法与之相反,将拥有指定标签的选项或指定序号方法与之相反,将拥有指定标签的选项或指定序号处的选项从列表中移出。

141、这两个方法使得程序可以处的选项从列表中移出。这两个方法使得程序可以动态调整列表所包含的选择项。动态调整列表所包含的选择项。(3) 事件响应事件响应列表可以产生两种事件:当用户单击列表中的某一个列表可以产生两种事件:当用户单击列表中的某一个选项并选中它时,将产生选项并选中它时,将产生ItemEvent类的选择事件;类的选择事件;当用户双击列表中的某个选项时,将产生当用户双击列表中的某个选项时,将产生ActionEvent类的动作事件。类的动作事件。如果程序希望对这两种事件都做出响应,就需要把列如果程序希望对这两种事件都做出响应,就需要把列表分别注册给表分别注册给ItemEvent的监听者的监听者

142、ItemListener和和ActionEvent的监听者的监听者ActionListener。MyList.addItemListener(this);MyList.addActionListener(this); 并在实现了监听者接口的类中分别定义响应选择事件并在实现了监听者接口的类中分别定义响应选择事件的方法和响应动作事件的方法。的方法和响应动作事件的方法。public void itemStateChanged(ItemEvent e); /响应单击响应单击的选择事件的选择事件public void actionPerformed(ActionEvent e); /响应双击响应双击的动

143、作事件的动作事件这样,当列表上发生了单击或双击动作时,系统就自这样,当列表上发生了单击或双击动作时,系统就自动调用上述两个方法来处理相应的选择或动作事件。动调用上述两个方法来处理相应的选择或动作事件。通常在通常在itemStateChanged(ItemEvent e)方法里,会调方法里,会调用用e.getItemSelectable( )方法获得产生这个选择事件方法获得产生这个选择事件的列表的列表(List)对象的引用,再利用列表对象的方法对象的引用,再利用列表对象的方法getSelectedIndex( )或或getSelectedItem( )就可以方便地得知用户选择就可以方便地得知用户

144、选择了列表的哪个选项。与了列表的哪个选项。与Checkbox的使用方法类似,的使用方法类似,e.getItemSelectable( )的返回值需要先强制类型转化成的返回值需要先强制类型转化成List对象,然后对象,然后才能调用才能调用List类的方法。例如:类的方法。例如:String s = (List)e.getItemSelectable( ).getSelectedItem( );而在而在actionPerformed(ActionEvent e)方法里,调用方法里,调用e.getSource( )可以得到产生此动作事件的可以得到产生此动作事件的List对象引用,同样对象引用,同样要

145、使用强制类型转换。要使用强制类型转换。(List)e.getSource( ); 调用调用e.getActionCommand( )可以获得事件的选项的可以获得事件的选项的字符串标签,在列表单选的情况下,相当于执行字符串标签,在列表单选的情况下,相当于执行(List)e.getSource( ).getSelectedItem( );的运行结果。需要注意,列表的双击事件并不能覆的运行结果。需要注意,列表的双击事件并不能覆盖单击事件。当用户双击一个列表选项时,首先产盖单击事件。当用户双击一个列表选项时,首先产生一个单击的选项事件,然后再产生一个双击的动生一个单击的选项事件,然后再产生一个双击的动

146、作事件。如果定义并注册了两种事件的监听者,作事件。如果定义并注册了两种事件的监听者,itemStateChanged( )方法和方法和actionPerformed( )方法将分别被先后调用。方法将分别被先后调用。例例 7-11 TestList.java1: import java.applet.*;2: import java.awt.*;3: import java.awt.event.*;4:5: public class TestList extends Applet implements ActionListener,ItemListener6: 7: List MyList;8:

147、 Label result;9: public void init( ) 10: 11: result = new Label(您双击了选项您双击了选项);12: MyList = new List(4,true);13: MyList.add(北京北京);14: MyList.add(上海上海);15: MyList.add(南京南京);16: MyList.add(西安西安);17: MyList.add(重庆重庆);18: MyList.add(深圳深圳);19: add(MyList);20: add(result);21: MyList.addActionListener(this)

148、;22: MyList.addItemListener(this);23: 24: public void actionPerformed(ActionEvent e)25: 26: if(e.getSource( )=MyList)27: result.setText(您双击了选项您双击了选项 +e.getActionCommand( );28: 29: public void itemStateChanged(ItemEvent e)30: 31: List temp;32: String sList;33: String mgr = new String();34: if(e.getIt

149、emSelectable( ) instanceof List)35: 36: temp = (List)(e.getItemSelectable( );37: sList = temp.getSelectedItems( );38: for(int i=0;isList.length;i+)39: mgr = mgr + sListi + ;40: showStatus(mgr);41: 42: 43: 图图 7.13 例例7-11的运行结果的运行结果 图图7.13是例是例7-11的运行结果。例的运行结果。例7-11定义的定义的Applet是是动作事件和选择事件这两种事件的监听者,它实现动作

150、事件和选择事件这两种事件的监听者,它实现了了ActionListener和和ItemListener两个接口,其中包两个接口,其中包括一个列表对象括一个列表对象MyList和一个用来显示数据的标签和一个用来显示数据的标签对象对象result。第。第12句创建了一个可以复选一次显示句创建了一个可以复选一次显示4个选项的个选项的List对象对象MyList。第。第13到第到第18句利用句利用add( )方法向方法向MyList中加入了中加入了6个字符串选项,分别代表个字符串选项,分别代表6个不同的城市。第个不同的城市。第24到第到第28句定义的句定义的actionPerform( )方法用来响应用

151、户双击方法用来响应用户双击List选项的动作事件,将选项的动作事件,将用户双击的选项字符串显示在标签用户双击的选项字符串显示在标签result中。中。第第29到第到第42句定义的句定义的itemStateChanged( )方法用来响方法用来响应用户单击应用户单击List选项的操作,并利用选项的操作,并利用getSelectedItems( )方法将所有的这些选项组合成一个字符串显示在方法将所有的这些选项组合成一个字符串显示在Applet的状态条中。第的状态条中。第40句的方法句的方法showStatus( )是是Applet对象的方法,它将参数字符串显示在对象的方法,它将参数字符串显示在Ap

152、plet的状态条中。的状态条中。 列表复选情况下的处理比较复杂,但是基本原理是一列表复选情况下的处理比较复杂,但是基本原理是一样的。通常,需要响应列表事件的情况不多,与样的。通常,需要响应列表事件的情况不多,与Checkbox一样,程序更关心的是某个特定的时刻。一样,程序更关心的是某个特定的时刻。例如用户单击例如用户单击“输入输入”按钮的时刻、列表最终的选按钮的时刻、列表最终的选择情况等。这可以通过调用列表自身的方法,如择情况等。这可以通过调用列表自身的方法,如getSelectedIndex( )或或getSelectedItem( )来获得。来获得。7.8 滚动条与调整事件滚动条与调整事件

153、 1. 调整事件调整事件(AdjustmentEvent)AdjustmentEvent类只包含一个事件类只包含一个事件ADJUSTMENT-VALUE-CHANGED事件。与事件。与ItemEvent事件引发的离散状态变化不同,事件引发的离散状态变化不同,ADJUSTMENT-VALUE-CHANGED是是GUI组件状组件状态发生连续变化的事件,引发这类事件的具体动作态发生连续变化的事件,引发这类事件的具体动作有:有:(1) 操纵滚动条操纵滚动条(Scrollbar)改变其滑块位置。改变其滑块位置。(2) 操纵用户自定义的操纵用户自定义的Scrollbar对象的子类组件,改对象的子类组件,改

154、变其滑块位置。变其滑块位置。AdjustmentEvent类的主要方法有:类的主要方法有:(1) public Adjustable getAdjustable( )这个方法返回引发状态变化事件的事件源,能够引发这个方法返回引发状态变化事件的事件源,能够引发状态变化事件的事件源都是实现了状态变化事件的事件源都是实现了Adjustable接口接口的类。例如,的类。例如,Scrollbar类就是实现了类就是实现了Adjustable接接口的类。口的类。Adjustable接口是接口是java.awt包中定义的一包中定义的一个接口,一个方法的返回值类型被标志为一个接口,个接口,一个方法的返回值类型被

155、标志为一个接口,代表这个方法将返回一个实现了这个接口的类的对代表这个方法将返回一个实现了这个接口的类的对象。例如,调用象。例如,调用getAdjustable( )方法将返回引发这方法将返回引发这个事件的个事件的Scrollbar对象的引用。对象的引用。(2) public int getAdjustmentType( )这个方法返回状态变化事件的状态变化类型,其返回这个方法返回状态变化事件的状态变化类型,其返回值在值在AdjustmentEvent类的几个静态常量所列举的类的几个静态常量所列举的集合之内。集合之内。AdjustmentEvent.BLOCK-DECREMENT: 代表点代表点

156、击滚动条下方引发块状下移的动作。击滚动条下方引发块状下移的动作。AdjustmentEvent.BLOCK-INCREMENT: 代表点代表点击滚动条上方引发块状上移的动作。击滚动条上方引发块状上移的动作。AdjustmentEvent.TRACK:代表拖动滚动条滑块的:代表拖动滚动条滑块的动作。动作。AdjustmentEvent.UNIT-DECREMENT: 代表点击代表点击滚动条下三角按钮引发最小单位下移的动作。滚动条下三角按钮引发最小单位下移的动作。AdjustmentEvent.UNIT-INCREMENT: 代表点击滚代表点击滚动条上三角按钮引发最小单位上移的动作。动条上三角按钮

157、引发最小单位上移的动作。通过调用通过调用getAdjustmentType( )方法并比较其返回值,方法并比较其返回值,就可以得知用户发出的哪种操作引发了哪种连续的就可以得知用户发出的哪种操作引发了哪种连续的状态变动。状态变动。(3) public int getValue( )调用调用getValue( )方法可以返回状态变化后的滑块对应方法可以返回状态变化后的滑块对应的当前数值。滑块是可以连续调整的,调整将引发的当前数值。滑块是可以连续调整的,调整将引发AdjustmentEvent事件,事件,getValue( )方法可以返回调方法可以返回调整后滑块对应的最新数值。整后滑块对应的最新数值

158、。 2. 滚动条滚动条(Scrollbar)(1) 创建创建滚动条是一种比较特殊的滚动条是一种比较特殊的GUI组件,它能够接受并体组件,它能够接受并体现连续的变化,称为现连续的变化,称为“调整调整”。创建。创建Scrollbar类的类的对象将创建一个含有滚动槽、增加箭头、减少箭头对象将创建一个含有滚动槽、增加箭头、减少箭头和滑块和滑块(也称为气泡也称为气泡)的滚动条。的滚动条。Scrollbar mySlider = new Scrollbar(Scrollbar.HORIZONTAL,50,1,0,100);上述语句创建的滚动条可以参看图上述语句创建的滚动条可以参看图7.14。 图图 7.1

159、4 滚动条的各组成部分滚动条的各组成部分 构造函数的第一个参数说明新滚动条的方向,使用常构造函数的第一个参数说明新滚动条的方向,使用常量量Scrollbar.HORIZONTAL将创建横向滚动条,使将创建横向滚动条,使用常量用常量Scrollbar.VERTICAL将创建纵向滚动条。将创建纵向滚动条。构造函数的第二个参数用来说明滑块最初的显示位置,构造函数的第二个参数用来说明滑块最初的显示位置,它应该是一个整型量。它应该是一个整型量。构造函数的第三个参数说明滑块的大小,对滑块滚动构造函数的第三个参数说明滑块的大小,对滑块滚动同时引起文本区域滚动的情况,滑块大小与整个滚同时引起文本区域滚动的情况

160、,滑块大小与整个滚动槽长度的比例应该与窗口中可视的文本区域与整动槽长度的比例应该与窗口中可视的文本区域与整个文本区域的比例相当,对于滑块滚动不引起文本个文本区域的比例相当,对于滑块滚动不引起文本区域滚动的情况,可把滑块大小设为区域滚动的情况,可把滑块大小设为1。构造函数的第四个参数说明滚动槽代表的最小数据。构造函数的第四个参数说明滚动槽代表的最小数据。构造函数的第五个参数说明滚动槽代表的最大数据。构造函数的第五个参数说明滚动槽代表的最大数据。(2) 常用方法常用方法对于新创建的滚动条,设置它的单位增量和块增量还对于新创建的滚动条,设置它的单位增量和块增量还需要调用如下的方法。需要调用如下的方法

161、。mySlider.setUnitIncrement(1);mySlider.setBlockIncrement(50); setUnitIncrement(int)方法指定滚动条的单位增量,方法指定滚动条的单位增量,即用户单击滚动条两端的三角按钮时代表的数据改即用户单击滚动条两端的三角按钮时代表的数据改变;变;setBlockIncrement(int)方法指定滚动条的块增方法指定滚动条的块增量,即用户单击滚动槽时代表的数据改变量,即用户单击滚动槽时代表的数据改变(如图如图7.14所示所示)。与上面两个方法相对应,滚动条类还定义。与上面两个方法相对应,滚动条类还定义了了getUnitIncr

162、ement( )方法和方法和getBlockIncrement( )方法来分别获取滚动条的单位增量和块增量。方法来分别获取滚动条的单位增量和块增量。getValue( )方法返回当前滑块位置代表的整数值,当方法返回当前滑块位置代表的整数值,当用户利用滚动条改变滑块在滚动槽中的位置时,用户利用滚动条改变滑块在滚动槽中的位置时,getValue( )方法的返回值将相应随之改变。方法的返回值将相应随之改变。(3) 事件响应事件响应滚动条可以引发滚动条可以引发AdjustmentEvent类代表的调整事件,类代表的调整事件,当用户通过各种方式改变滑块位置从而改变其代表当用户通过各种方式改变滑块位置从而

163、改变其代表的数值时,都会引发调整事件。的数值时,都会引发调整事件。程序要响应滚动条引发的调整事件,必须首先把这个程序要响应滚动条引发的调整事件,必须首先把这个滚动条注册给实现了滚动条注册给实现了AdjustmentListener接口的调接口的调整事件监听者。整事件监听者。mySlider.addAdjustmentListener(this);调整事件监听者中用于响应调整事件的方法是:调整事件监听者中用于响应调整事件的方法是:public void adjustmentValueChanged(AdjustmentEvent e); 这个方法通常需要调用这个方法通常需要调用e.getAdju

164、stable( )来获得引发来获得引发当前调整事件的事件源,如滚动条。另一个有用的当前调整事件的事件源,如滚动条。另一个有用的方法是方法是AdjustmentEvent类的方法类的方法getValue( ),它与,它与滚动条的滚动条的getValue( )方法功能相同,方法功能相同,e.getValue( )方方法可以返回调整事件后的数值。调用法可以返回调整事件后的数值。调用e.getAdjustmentType( )方法可以知道当前调整事件的类型,即用户使用方法可以知道当前调整事件的类型,即用户使用何种方式改变了滚动条滑块的位置。具体方法是把何种方式改变了滚动条滑块的位置。具体方法是把这个方

165、法的返回值与这个方法的返回值与AdjustmentEvent类的几个静类的几个静态常量相比较。态常量相比较。 AdjustmentEvent.BLOCK-INCREMENT:块增加。:块增加。AdjustmentEvent.BLOCK-DECREMENT:块减少。:块减少。AdjustmentEvent.UNIT-INCREMENT:单位增加。:单位增加。AdjustmentEvent.UNIT-DECREMENT:单位减少。:单位减少。AdjustmentEvent.TRACK:用鼠标拖动滑块移动。:用鼠标拖动滑块移动。例例7-12是一个创建并使用滚动条的例子。是一个创建并使用滚动条的例子。

166、例例 7-12 TestSlider.java 1: import java.applet.*;2: import java.awt.*;3: import java.awt.event.*;4:5: public class TestSlider extends Applet implements AdjustmentListener6: 7: Scrollbar mySlider;8: TextField sliderValue;9:10: public void init( )11: 12: setLayout(new BorderLayout( );13: mySlider = 14:

167、 new Scrollbar(Scrollbar.HORIZONTAL,0,1,0,Integer.MAX-VALUE); 15: mySlider.setUnitIncrement(1);16: mySlider.setBlockIncrement(50);17: add(South,mySlider);18: mySlider.addAdjustmentListener(this);19: sliderValue = new TextField(30);20: add(Center,sliderValue);21: 22: public void adjustmentValueChange

168、d(AdjustmentEvent e)23: 24: int value;25: if(e.getAdjustable( ) = mySlider)26: 27: value = e.getValue( );28: sliderValue.setText(new Integer(int)value).toString( );29: sliderValue.setBackground(new Color(value);30: 31: 32: 例例7-12的运行结果如图的运行结果如图7.14所示。例所示。例7-12的程序定义的程序定义了一个实现了了一个实现了AdjustmentListener接

169、口的接口的Applet,包含一个包含一个Scrollbar对象对象mySlider和一个文本框对象和一个文本框对象sliderValue。第。第12句把句把Applet的布局策略设置为的布局策略设置为BorderLayout,第,第13,14句创建了句创建了mySlider对象。对象。第第15,16句设置这个滚动条的有关属性。第句设置这个滚动条的有关属性。第17句把句把它加入到它加入到Applet里面。第里面。第18句将它注册给调整事件句将它注册给调整事件的监听者。第的监听者。第22到到31句定义的句定义的adjustment ValueChanged( )方法首先判断引发调整事件的事件源是否

170、是方法首先判断引发调整事件的事件源是否是mySlider对象,然后调用对象,然后调用getValue( )方法获得调整方法获得调整后滚动条指向的数值。第后滚动条指向的数值。第28句在文本框对象中显示句在文本框对象中显示这个数值。第这个数值。第29句将文本框的背景色设置成滚动条句将文本框的背景色设置成滚动条数值对应的颜色。数值对应的颜色。7.9 画布与鼠标、键盘事件画布与鼠标、键盘事件 1. 鼠标事件鼠标事件(MouseEvent)MouseEvent类和类和KeyEvent类都是类都是InputEvent类的子类的子类,类,InputEvent类不包含任何具体的事件,但是调类不包含任何具体的事

171、件,但是调用用InputEvent类的类的getModifiers( )方法,并把返回值方法,并把返回值与与InputEvent类的几个静态整型常量类的几个静态整型常量ALT-MASK,CTRL-MASK,SHIFT-MASK,META-MASK,BUTTON1-MASK,BUTTON,2-MASK,BUTTON3-MASK相比较,就可以得知用户在引发相比较,就可以得知用户在引发KeyEvent事件时是否同时按下了功能键,或者用户事件时是否同时按下了功能键,或者用户在单击鼠标时单击的是哪个鼠标键。在单击鼠标时单击的是哪个鼠标键。 MouseEvent类包含如下的若干个鼠标事件,分别用类包含如下

172、的若干个鼠标事件,分别用MouseEvent类的同名静态整型常量标志。类的同名静态整型常量标志。(1) MOUSE-CLICKED:代表鼠标点击事件。:代表鼠标点击事件。(2) MOUSE-DRAGGED:代表鼠标拖动事件。:代表鼠标拖动事件。(3) MOUSE-ENTERED:代表鼠标进入事件。:代表鼠标进入事件。(4) MOUSE-EXITED:代表鼠标离开事件。:代表鼠标离开事件。(5) MOUSE-MOVED:代表鼠标移动事件。:代表鼠标移动事件。(6) MOUSE-PRESSED:代表鼠标按钮按下事件。:代表鼠标按钮按下事件。(7) MOUSE-RELEASED:代表鼠标按钮松开事件

173、。:代表鼠标按钮松开事件。 调用调用MouseEvent对象的对象的getID( )方法并把返回值与上方法并把返回值与上述各常量比较,就可以知道用户引发的是哪个具体述各常量比较,就可以知道用户引发的是哪个具体的鼠标事件。例如假设的鼠标事件。例如假设mouseEvt是是MouseEvent类类的对象,下面的语句将判断它代表的事件是否是的对象,下面的语句将判断它代表的事件是否是MOUSE-CLICKED:if ( mouseEvt . getID( ) = MouseEvent. MOUSE-CLICKED )不过一般不需要这样处理,因为监听不过一般不需要这样处理,因为监听MouseEvent事事

174、件的监听者件的监听者MouseListener和和MouseMotionListener中有七个具体方法,分别针对上述的七个具体鼠标中有七个具体方法,分别针对上述的七个具体鼠标事件,系统会分辨鼠标事件的类型并自动调用相关事件,系统会分辨鼠标事件的类型并自动调用相关的方法,所以编程者只需把处理相关事件的代码放的方法,所以编程者只需把处理相关事件的代码放到相关的方法里即可。到相关的方法里即可。MouseEvent类有如下主要方法,类有如下主要方法,(1) public int getX( ): 返回发生鼠标事件的返回发生鼠标事件的X坐标。坐标。(2) public int getY( ): 返回发

175、生鼠标事件的返回发生鼠标事件的Y坐标。坐标。(3) public Point getPoint( ): 返回返回Point对象,包含鼠对象,包含鼠标事件发生的坐标点。标事件发生的坐标点。(4) public int getClickCount( ): 返回鼠标点击事件返回鼠标点击事件的点击次数。的点击次数。前面所说的前面所说的MouseListener和和MouseMotionListener的的几个具体的事件处理方法,都以几个具体的事件处理方法,都以MouseEvent类的类的对象为形式参数。通过调用对象为形式参数。通过调用MouseEvent类的上述类的上述方法,这些事件处理方法可以得到引

176、发它们的鼠标方法,这些事件处理方法可以得到引发它们的鼠标事件的具体信息。事件的具体信息。例例 7-13 ResponseToMouse.java 1: import java.applet.*;2: import java.awt.*;3: import java.awt.event.*;4:5: public class ResponseToMouse extends Applet 6: implements MouseListener, MouseMotionListener7: 8: public void init( )9: 10: this.addMouseListener(this

177、);11: this.addMouseMotionListener(this);12: 13: public void mouseClicked(MouseEvent e)14: 15: if(e.getClickCount( )=1)16: showStatus(您在您在(+e.getX( )+,+e.getY( )+)单击了鼠标。单击了鼠标。);17: else if(e.getClickCount( )=2)18: showStatus(您在您在(+e.getX( )+,+e.getY( )+)双击了鼠标。双击了鼠标。);19: 20: public void mouseEntered(

178、MouseEvent e)21: 22: showStatus(鼠标进入鼠标进入Applet。);23: 24: public void mouseExited(MouseEvent e)25: 26: showStatus(鼠标离开鼠标离开Applet。);27: 28: public void mousePressed(MouseEvent e)29: 30: showStatus(您按下了鼠标。您按下了鼠标。);31: 32: public void mouseReleased(MouseEvent e)33: 34: showStatus(您松开了鼠标。您松开了鼠标。);35: 36:

179、 public void mouseMoved(MouseEvent e)37: 38: showStatus(您移动了鼠标,新位置在您移动了鼠标,新位置在(+e.getX( )+,+e.getY( )+)。);39: 40: public void mouseDragged(MouseEvent e)41: 42: showStatus(您拖动了鼠标。您拖动了鼠标。);43: 44: 例例7-13中的程序定义了一个实现了中的程序定义了一个实现了MouseListener和和MouseMotionListener接口的接口的Applet,在,在Applet的的init( )方法中,第方法中,第

180、10和和11句把这个句把这个Applet分别注册给鼠分别注册给鼠标事件和鼠标动作事件的监听者。第标事件和鼠标动作事件的监听者。第13到到35句定义句定义的五个方法是对的五个方法是对MouseListener接口中定义的五个接口中定义的五个同名抽象方法的具体实现。第同名抽象方法的具体实现。第36到到43句定义的两个句定义的两个方法是对方法是对MouseMotionListner接口中定义的两个同接口中定义的两个同名抽象方法的具体实现。这个程序将监听所有的鼠名抽象方法的具体实现。这个程序将监听所有的鼠标事件并将监听到的事件信息显示在标事件并将监听到的事件信息显示在Applet的状态的状态条中。条中

181、。 2. 键盘事件键盘事件(KeyEvent)KeyEvent类包含如下三个具体的键盘事件,分别对类包含如下三个具体的键盘事件,分别对应应KeyEvent类的几个同名的静态整型常量。类的几个同名的静态整型常量。KEY-PRESSED: 代表键盘按键被按下的事件。代表键盘按键被按下的事件。KEY-RELEASED: 代表键盘按键被放开的事件。代表键盘按键被放开的事件。KEY-TYPED: 代表按键被敲击的事件。代表按键被敲击的事件。KeyEvent类的主要方法有:类的主要方法有:public char getKeyChar( )返回引发键盘事件的按键对应的返回引发键盘事件的按键对应的Unicod

182、e字符。如果字符。如果这个按键没有这个按键没有Unicode字符与之相对应,则返回字符与之相对应,则返回KeyEvent类的一个静态常量类的一个静态常量KeyEvent.CHAR-UNDEFINED。与与KeyEvent事件相对应的监听者接口是事件相对应的监听者接口是KeyListener,这个接口中定义了如下的三个抽象方法,分别与,这个接口中定义了如下的三个抽象方法,分别与KeyEvent中的三个具体事件类型相对应。中的三个具体事件类型相对应。(1) public void keyPressed(KeyEvent e);(2) public void keyReleased(KeyEvent

183、 e);(3) public void keyTyped(KeyEvent e);可见,事件类中的事件类型名与对应的监听者接口中可见,事件类中的事件类型名与对应的监听者接口中的抽象方法名很相似,也体现了二者之间的响应关的抽象方法名很相似,也体现了二者之间的响应关系。凡是实现了系。凡是实现了KeyListener接口的类,都必须具接口的类,都必须具体实现上述的三个抽象方法,把用户程序对这三种体实现上述的三个抽象方法,把用户程序对这三种具体事件的响应代码放在实现后的方法体中,这些具体事件的响应代码放在实现后的方法体中,这些代码里通常需要用到实参代码里通常需要用到实参KeyEvent对象对象e的若干

184、信的若干信息,这可以通过调用息,这可以通过调用e的方法,如的方法,如getSource( ),getKeyChar( )等来实现。例如,下面的语句将判断用户键入了等来实现。例如,下面的语句将判断用户键入了y还是还是n,代表肯定或否定的回答。,代表肯定或否定的回答。 public void keyPressed(KeyEvent e)char ch = e.getKeyChar( );if(ch = y | ch = Y) m-result.setText(同意同意);else if(ch = n | ch = N) m-result.setText(反对反对);else m-result.se

185、tText(非法输入非法输入);其中其中m-result是一个用来输出信息的是一个用来输出信息的Label对象。对象。3. 画布画布(Canvas)画布是一个用来画图的矩形背景组件,在画布里可以画布是一个用来画图的矩形背景组件,在画布里可以像在像在Applet里那样绘制各种图形,也可以响应鼠标里那样绘制各种图形,也可以响应鼠标和键盘事件。和键盘事件。(1) 创建创建Canvas的构造函数没有参数,所以使用简单的语句的构造函数没有参数,所以使用简单的语句就可以创建一个画布对象。就可以创建一个画布对象。Canvas myCanvas = new Canvas( );在创建了在创建了Canvas对象

186、之后,还应该对象之后,还应该调用调用setSize( )方法确定这个画布对象的大小,否则方法确定这个画布对象的大小,否则用户在运行界面中将看不到这个画布。用户在运行界面中将看不到这个画布。 (2) 常用方法常用方法Canvas大小的常用方法只有一个大小的常用方法只有一个public void paint(Graphics g),用户程序重载这个方法就可以,用户程序重载这个方法就可以实现在实现在Canvas上面绘制有关图形。上面绘制有关图形。(3) 产生事件产生事件Canvas对象与对象与Applet相似,可以引发键盘和鼠标事件。相似,可以引发键盘和鼠标事件。例例 7-14 TestCanvas

187、.java 1: import java.applet.*;2: import java.awt.*;3: import java.awt.event.*;4:5: public class TestCanvas extends Applet 6: 7: CanvasDraw cd;8:9: public void init( )10: 11: cd = new CanvasDraw(new Dimension(200,180),this);12: cd.setBackground(Color.pink);13: add(cd);14: cd.requestFocus( );15: 16: 1

188、7: class CanvasDraw extends Canvas implements KeyListener18: 19: Applet m-Parent;20: boolean m-bFlag = false;21: int currentX=0,currentY=0,startX=0,startY=0;22: StringBuffer sb = new StringBuffer( );23: CanvasDraw(Dimension d,Applet p)24: 25: m-Parent = p;26: setSize(d);27: setBackground(Color.gray)

189、;28: addKeyListener(this);29: addMouseListener(new MouseAdpt(this);30: addMouseMotionListener(new MouseMotionAdpt(this);31: 32: void setStart(int x,int y)33: 34: startX = x;35: startY = y;36: 37: void setCurrent(int x,int y)38: 39: currentX = x;40: currentY = y;41: 42: void setMouseDragged(boolean b

190、) 43: 44: m-bFlag = b;45: 46: void showMeg(String s)47: 48: m-Parent.showStatus(s);49: 50: void clearAll( )51: 52: startX = 0;53: startY = 0;54: currentX = 0;55: currentY = 0;56: repaint( );57: 58: public void keyTyped(KeyEvent e)59: 60: char ch = e.getKeyChar( );61: sb.append(ch);62: showMeg (击键击键+

191、sb.toString( );63: repaint( );64: 65: public void keyPressed(KeyEvent e) 66: public void keyReleased(KeyEvent e)67: public void paint(Graphics g)68: 69: g.drawString(+currentX+,+currentY+) +sb,10,20);70: if(m-bFlag)71: g.drawLine(startX,startY,currentX,currentY);72: 73: 74: class MouseAdpt extends M

192、ouseAdapter75: 76: CanvasDraw m-Parent;77: MouseAdpt(CanvasDraw p)78: 79: m-Parent = p;80: 81: public void mousePressed(MouseEvent e)82: 83: m-Parent.setStart(e.getX( ),e.getY( );84: m-Parent.showMeg(您开始画线您开始画线);85: 86: public void mouseReleased(MouseEvent e)87: 88: m-Parent.showMeg(您画出了一条直线您画出了一条直线

193、);89: 90: public void mouseEntered(MouseEvent e)91: 92: m-Parent.showMeg(鼠标进入画布鼠标进入画布);93: 94: public void mouseExited(MouseEvent e)95: 96: m-Parent.showMeg(鼠标移出画布鼠标移出画布);97: 98: 99: class MouseMotionAdpt extends MouseMotionAdapter100: 101: CanvasDraw m-Parent;102: MouseMotionAdpt(CanvasDraw p)103:

194、104: m-Parent = p;105: 106: public void mouseMoved(MouseEvent e) 107: 108: m-Parent.setCurrent(e.getX( ),e.getY( );109: m-Parent.setMouseDragged(false);110: m-Parent.repaint(10,0,60,30);111: 112: public void mouseDragged(MouseEvent e)113: 114: m-Parent.setCurrent(e.getX( ),e.getY( );115: m-Parent.se

195、tMouseDragged(true);116: m-Parent.repaint( );117: 118: 图图 7.15 例例7-14的运行结果的运行结果 图图7.15是例是例7-14的运行结果。这个程序一共定义了四的运行结果。这个程序一共定义了四个类,其中个类,其中CanvasDraw是用户定义的系统类是用户定义的系统类Canvas类的子类,第类的子类,第19句定义的句定义的Applet对象对象m-Parent是是CanvasDraw包含对象的包含对象的Applet对象的引对象的引用,布尔量用,布尔量m-bFlag是用户是否在用鼠标画直线的是用户是否在用鼠标画直线的标志,标志,start

196、X和和startY是所画直线的起点坐标,是所画直线的起点坐标,currentX和和currentY是当前的鼠标位置,是当前的鼠标位置,StringBuffer对象对象sb用来保存用户击键所键入的字用来保存用户击键所键入的字符。注意,符。注意,Canvas对象及其子类对象是基本组件而对象及其子类对象是基本组件而不是容器。不是容器。CanvasDraw对象可以响应鼠标事件和键盘事件,它对象可以响应鼠标事件和键盘事件,它实现了实现了KeyListener接口,重载了其中的三个抽象接口,重载了其中的三个抽象方法,但是只给方法,但是只给keyTyped( )方法书写了具体的方法方法书写了具体的方法体,把

197、用户键入的字符保存在体,把用户键入的字符保存在sb对象中并显示在状对象中并显示在状态条中。态条中。MouseListener和和MouseMotionListener中中的抽象方法较多。如果的抽象方法较多。如果CanvasDraw实现了这两个实现了这两个接口,就必须重载所有的七个抽象方法,而程序实接口,就必须重载所有的七个抽象方法,而程序实际只用到了其中的两三个方法。际只用到了其中的两三个方法。 为解决这个问题,例为解决这个问题,例7-14中使用了事件剪裁类中使用了事件剪裁类MouseAdapter和和Mouse MotionAdapter。每个监听。每个监听者接口都对应一个事件剪裁类,事件剪

198、裁将用空的者接口都对应一个事件剪裁类,事件剪裁将用空的方法体具体实现对应监听者接口中的每个方法。例方法体具体实现对应监听者接口中的每个方法。例如如MouseAdapter定义如下:定义如下: public class MouseAdapter implements MouseListener public void mouseClicked(MouseEvent e) public void mousePressed(MouseEvent e) public void mouseReleased(MouseEvent e) public void mouseEntered(MouseEvent

199、 e) public void mouseExited(MouseEvent e) 这样,一个类只要以这样,一个类只要以MouseAdapter类为父类,就可类为父类,就可以只重载少数几个程序中真正用到的方法,使程序以只重载少数几个程序中真正用到的方法,使程序简洁。例简洁。例7-14中定义的中定义的MouseAdpt 类和类和MouseMotionAdpt类就是这样专门用来响应鼠标事类就是这样专门用来响应鼠标事件的剪裁类的子类。程序将显示鼠标的当前位置并件的剪裁类的子类。程序将显示鼠标的当前位置并响应鼠标的拖动操作在响应鼠标的拖动操作在Canvas上画直线。上画直线。TestCanvas类是程

200、序主类,其中包含一个类是程序主类,其中包含一个CanvasDraw的对象。的对象。7.10 布局设计布局设计 在在前前面面的的例例子子中中,基基本本组组件件仅仅仅仅被被简简单单地地加加入入容容器器。如如果果程程序序需需要要进进一一步步考考虑虑如如何何设设计计和和控控制制这这些些组组件件在在容容器器中中的的位位置置和和相相互互关关系系,就就需需要要学学习习布布局局设设计计的知识。的知识。在在Java的的GUI界面设计中,布局控制是通过为容器设界面设计中,布局控制是通过为容器设置布局编辑器来实现的。置布局编辑器来实现的。java.awt包中共定义了五包中共定义了五种布局编辑类,每个布局编辑类对应一

201、种布局策略,种布局编辑类,每个布局编辑类对应一种布局策略,分别是分别是FlowLayout,BorderLayout,CardLayout,GridLayout和和GridBagLayout。当一个容器选定。当一个容器选定一种布局策略时,它应该创建该策略对应的布局编一种布局策略时,它应该创建该策略对应的布局编辑类的对象,并将此对象设置为自己的布局编辑器。辑类的对象,并将此对象设置为自己的布局编辑器。没有设置布局编辑器的容器,其中的对象会互相覆没有设置布局编辑器的容器,其中的对象会互相覆盖、遮挡,影响使用,所以必须为每个容器设置一盖、遮挡,影响使用,所以必须为每个容器设置一个合适的布局编辑器。下

202、面将详细讨论这几种布局个合适的布局编辑器。下面将详细讨论这几种布局编辑策略。编辑策略。7.10.1 FlowLayout FlowLayout是容器是容器Panel和它的子类和它的子类Applet缺省使用缺省使用的布局编辑策略,如果不专门为的布局编辑策略,如果不专门为Panel或或Applet指指定布局编辑器,则它们就使用定布局编辑器,则它们就使用FlowLayout的布局策的布局策略。略。FlowLayout对应的布局策略非常简单。遵循这种策对应的布局策略非常简单。遵循这种策略的容器将其中的组件按照加入的先后顺序从左向略的容器将其中的组件按照加入的先后顺序从左向右排列,一行排满之后就下转到下

203、一行继续从左至右排列,一行排满之后就下转到下一行继续从左至右排列,每一行中的组件都居中排列;在组件不多右排列,每一行中的组件都居中排列;在组件不多时,使用这种策略非常方便,但是当容器内的时,使用这种策略非常方便,但是当容器内的GUI元素增加时,就显得高低参差不齐。元素增加时,就显得高低参差不齐。对于使用对于使用FlowLayout的容器,加入组件使用如下简的容器,加入组件使用如下简单的命令:单的命令:add(组件名组件名);即可,这些组件将顺序地排列在容器中,有时由于即可,这些组件将顺序地排列在容器中,有时由于FlowLayout的布局能力有限,程序会采用容器嵌套的布局能力有限,程序会采用容器

204、嵌套的方法,即把一个容器当作一个组件加入另一个容的方法,即把一个容器当作一个组件加入另一个容器,这个容器组件可以有自己的组件和自己的布局器,这个容器组件可以有自己的组件和自己的布局策略,使整个容器的布局达到应用的需求。策略,使整个容器的布局达到应用的需求。对于一个原本不使用对于一个原本不使用FlowLayout布局编辑器的容器,布局编辑器的容器,若需要将其布局策略改为若需要将其布局策略改为FlowLayout,可以使用如,可以使用如下的语句:下的语句:setLayout(new FlowLayout( );setLayout( )方法是所有容器的父类方法是所有容器的父类Container的方法

205、,的方法,用于为容器设定布局编辑器。创建用于为容器设定布局编辑器。创建FlowLayout类的类的对象可以使用上面语句中的无参数构造函数,也可对象可以使用上面语句中的无参数构造函数,也可以使用下面的两种构造函数:以使用下面的两种构造函数:(1) FlowLayout(int align, int hgap, int vgap)参数参数align指定每行组件的对齐方式,可以取三个静指定每行组件的对齐方式,可以取三个静态常量态常量LEFT,CENTER,RIGHT之一之一;参数参数hgap和参数和参数vgap分别指定各组件间的横向和纵向间的以分别指定各组件间的横向和纵向间的以像素为单位的间距。像素

206、为单位的间距。(2) FlowLayout(int align)参数参数align指定每行组件的对齐方法,组件间的横纵指定每行组件的对齐方法,组件间的横纵间距都固定为五个像素;无参数的构造函数创建的间距都固定为五个像素;无参数的构造函数创建的FlowLayout对象,其对齐方式为对象,其对齐方式为CENTER常量指常量指定的居中方式,组件间的横纵间距都为五个像素。定的居中方式,组件间的横纵间距都为五个像素。7.10.2 BorderLayout BorderLayout也是一种简单的布局策略,它把容器也是一种简单的布局策略,它把容器内的空间简单地划分为东、西、南、北、中五个区内的空间简单地划分

207、为东、西、南、北、中五个区域域(如图如图7.16所示所示),每加入一个组件都应该指明把,每加入一个组件都应该指明把这个组件加在哪个区域中。这个组件加在哪个区域中。分布在北部和南部区域的组件将横向扩展至占据整个分布在北部和南部区域的组件将横向扩展至占据整个容器的长度,分布在东部和西部的组件将伸展至占容器的长度,分布在东部和西部的组件将伸展至占据容器剩余部分的全部宽度,最后剩余的部分将分据容器剩余部分的全部宽度,最后剩余的部分将分配给位于中央的组件。如果某个区域没有分配组件,配给位于中央的组件。如果某个区域没有分配组件,则其他组件可以占据它的空间。例如,如果北部没则其他组件可以占据它的空间。例如,

208、如果北部没有分配组件,则西部和东部的组件将向上扩展到容有分配组件,则西部和东部的组件将向上扩展到容器的最上方,如果西部和东部没有分配组件,则位器的最上方,如果西部和东部没有分配组件,则位于中央的组件将横向扩展到容器的左右边界。于中央的组件将横向扩展到容器的左右边界。图图 7.16 一种布局策略一种布局策略使用无参数构造函数创建的使用无参数构造函数创建的BorderLayout规定各组规定各组件间的横、纵间距都为件间的横、纵间距都为0。如果希望使用大于。如果希望使用大于0的间的间距,则可以使用距,则可以使用BorderLayout的另一个构造函数创的另一个构造函数创建它建它 。BorderLay

209、out(int hgap, int vgap);BorderLayout只能指定五个区域位置。如果容器中只能指定五个区域位置。如果容器中需要加入超过五个组件,就必须使用容器的嵌套或需要加入超过五个组件,就必须使用容器的嵌套或改用其他的布局策略。例改用其他的布局策略。例7-15中的中的Applet使用了使用了BorderLayout并分配了五个组件。并分配了五个组件。例例 7-15 TestBorderLayout.java1: import java.applet.*;2: import java.awt.*;3: import java.awt.event.*;4:5: public cla

210、ss TestBorderLayout extends Applet6: 7: Button north,south,west,east,center;8:9: public void init( )10: 11: setLayout(new BorderLayout( );/设置设置BorderLayout布局编辑器布局编辑器12: north = new Button(North);13: south = new Button(South);14: west = new Button(West);15: east = new Button(East);16: center = new Bu

211、tton(Center);17: add(East,east);/加入组件时分配区域加入组件时分配区域18: add(Center,center);19: add(North,north);20: add(South,south);21: add(West,west);22: 23: 例例7-15的运行结果可以参看图的运行结果可以参看图7.16。该例的。该例的Applet对对象中用象中用BorderLayout布局策略在五个位置分别加入布局策略在五个位置分别加入了五个按钮。了五个按钮。7.10.3 CardLayout 使用使用CardLayout的容器表面上可以容纳多个组件,的容器表面上可以

212、容纳多个组件,但是实际上同一时刻容器只能从这些组件中选出一但是实际上同一时刻容器只能从这些组件中选出一个来显示,就像一叠个来显示,就像一叠“扑克牌扑克牌”每次只能显示最上每次只能显示最上面的一张一样,这个被显示的组件将占据所有的容面的一张一样,这个被显示的组件将占据所有的容器空间。使用器空间。使用CardLayout的一般步骤如下:的一般步骤如下:(1) 创建创建CardLayout对象作为布局编辑器:对象作为布局编辑器:Mycard = new CardLayout( );(2) 使用容器的使用容器的setLayout( )方法为容器设置布局编辑方法为容器设置布局编辑器:器:setLayou

213、t(Mycard); (3) 调用容器的方法调用容器的方法add( )将组件加入容器,同时为将组件加入容器,同时为组件分配一个字符串的名字,以便布局编辑器根据组件分配一个字符串的名字,以便布局编辑器根据这个名字调用显示这个组件。这个名字调用显示这个组件。add (字符串,组件字符串,组件);(4) 调用调用CardLayout的方法的方法show( ),根据字符串名字,根据字符串名字显示一个组件:显示一个组件:show(容器名,字符串容器名,字符串);或按组件;或按组件加入容器的顺序显示组件,如加入容器的顺序显示组件,如first(容器名容器名)方法显方法显示第一个组件,示第一个组件,last

214、(容器名容器名)方法显示最后一个组件方法显示最后一个组件等。等。例例7-16使用了使用了CardLayout的布局策略,图的布局策略,图7.17是它的是它的运行结果。运行结果。 图图 7.17 例例7-16的运行结果的运行结果例例 7-16 TestCardLayout.java1: import java.applet.*;2: import java.awt.*;3: import java.awt.event.*;4:5: public class TestCardLayout extends Applet 6: 7: CardLayout MyCard = new CardLayout

215、( );/创建创建CardLayout布局编辑器对象布局编辑器对象8: Button btn1 = new Button(第一页第一页);9: Button btn2 = new Button(第二页第二页);10: Button btn3 = new Button(第三页第三页);11: Button btn4 = new Button(第四页第四页); 12: Button btn5 = new Button(第五页第五页);13:14: public void init( )15: 16: setLayout(MyCard);/设置容器的布局策略为设置容器的布局策略为 CardLayou

216、t17: add(第一页第一页,btn1);/加入组件并指定名字加入组件并指定名字18: add(第二页第二页,btn2);19: add(第三页第三页,btn3);20: add(第四页第四页,btn4);21: add(第五页第五页,btn5);22: btn1.addMouseListener(new MouseMoveCard(MyCard,this);23: btn2.addMouseListener(new MouseMoveCard(MyCard,this);24: btn3.addMouseListener(new MouseMoveCard(MyCard,this);25:

217、btn4.addMouseListener(new MouseMoveCard(MyCard,this);26: btn5.addMouseListener(new MouseMoveCard(MyCard,this);27: 28: 29: class MouseMoveCard extends MouseAdapter30: 31: CardLayout cl;32: Applet m-Parent;33: MouseMoveCard(CardLayout c,Applet a)34: 35: cl = c;36: m-Parent = a;37: 38: public void mous

218、eClicked(MouseEvent e)39: 40: if(e.getModifiers( )=InputEvent.BUTTON1-MASK)41: cl.next(m-Parent);42: else43: cl.previous(m-Parent);44: 45: 例例7-16中定义的中定义的Applet包含五个按钮,第包含五个按钮,第16句把第句把第7句创建的句创建的CardLayout对象对象MyCard设置为这个设置为这个Applet的布局策略。五个按钮响应鼠标事件,按左的布局策略。五个按钮响应鼠标事件,按左键跳到下一个按钮,按右键跳到前一个按钮。键跳到下一个按钮,按右键跳到

219、前一个按钮。 7.10.4 GridLayout GridLayout是使用较多的布局编辑器,其基本布局是使用较多的布局编辑器,其基本布局策略是把容器的空间划分成若干行乘若干列的网格策略是把容器的空间划分成若干行乘若干列的网格区域,组件就位于这些划分出来的小格中。区域,组件就位于这些划分出来的小格中。GridLayout比较灵活,划分多少网格由程序自由控比较灵活,划分多少网格由程序自由控制,而且组件定位也比较精确。制,而且组件定位也比较精确。使用使用GridLayout布局编辑器的一般步骤如下:布局编辑器的一般步骤如下:(1) 创建创建GridLayout对象作为布局编辑器。指定划分对象作为布

220、局编辑器。指定划分网格的行数和列数,并使用容器的网格的行数和列数,并使用容器的setLayout( )方法方法为容器设置这个布局编辑器:为容器设置这个布局编辑器:setLayout(new GridLayout(行数行数, 列数列数)。 (2) 调用容器的方法调用容器的方法add( )将组件加入容器。组件填将组件加入容器。组件填入容器的顺序将按照第一行第一个、第一行第二个入容器的顺序将按照第一行第一个、第一行第二个第一行最后一个、第二行第一个第一行最后一个、第二行第一个最后一行最后一行最后一个进行。每个网格中都必须填入组件,如果最后一个进行。每个网格中都必须填入组件,如果希望某个网格为空白,可

221、以为它加入一个空的标签:希望某个网格为空白,可以为它加入一个空的标签:add (new Label( )。例例7-17使用了使用了GridLayout,图,图7.18是其运行结果。是其运行结果。 图图 7.18 例例7-17的运行结果的运行结果 例例 7-17 TestGridLayout.java1: import java.applet.*;2: import java.awt.*;3: import java.awt.event.*;4:5: public class TestGridLayout extends Applet6: 7: public void init( )8: 9:

222、setLayout(new GridLayout(5,6);/GridLayout 布局策略布局策略5行行6列列30网格网格10: for(int i=0;i5;i+)11: for(int j=0;j=50)14: add(new Button(Integer.toString(i*6+j);/随机加入按钮随机加入按钮15: else16: add(new Label( ); /随机加入空白随机加入空白17: 18: 19: 图图7.18(b)是利用随机数随机地产生按钮或空白填充是利用随机数随机地产生按钮或空白填充GridLayout的网格,把例的网格,把例7-17的语句:的语句: if(i

223、nt)(Math.random( )*100)=50)改为:改为: if(int)(Math.random( )*100)=0)得到的。图得到的。图7.18(a)是所有区域全部填充为按钮的情是所有区域全部填充为按钮的情况,从中可以清楚地看出况,从中可以清楚地看出GridLayout的布局策略和的布局策略和网格划分。网格划分。 GridBagLayout是五种布局策略中使用最复杂、功能是五种布局策略中使用最复杂、功能最强大的一种,它是在最强大的一种,它是在GridLayout的基础上发展而的基础上发展而来。因为来。因为GridLayout中的每个网格都是大小相同,中的每个网格都是大小相同,并且强

224、制组件与网格大小也相同,从而使得容器中并且强制组件与网格大小也相同,从而使得容器中的每个组件也都是相同的大小,显得很不自然,而的每个组件也都是相同的大小,显得很不自然,而且组件加入容器也必须按照固定的行列顺序,因此且组件加入容器也必须按照固定的行列顺序,因此不够灵活。在不够灵活。在GridBagLayout中,可以为每个组件中,可以为每个组件指定其包含的网格个数,可以保留组件原来的大小,指定其包含的网格个数,可以保留组件原来的大小,可以以任意顺序随意加入容器的任意位置,从而可可以以任意顺序随意加入容器的任意位置,从而可以真正自由地安排容器中每个组件的大小和位置。以真正自由地安排容器中每个组件的

225、大小和位置。7.11 Panel与容器事件与容器事件 从本节开始,将详细讨论从本节开始,将详细讨论GUI各种容器及其使用方法。各种容器及其使用方法。1. Container类类Container类是一个抽象类,里面包含了所有容器组类是一个抽象类,里面包含了所有容器组件都必须具有的方法和功能。件都必须具有的方法和功能。(1) add( ): Container类中有多个经过重载的类中有多个经过重载的add( )方法,其作用都是把方法,其作用都是把Component组件,可能是一个组件,可能是一个基本组件,也可能是另一个容器组件,加入到当前基本组件,也可能是另一个容器组件,加入到当前容器中。每个被

226、加入容器的组件根据加入的先后顺容器中。每个被加入容器的组件根据加入的先后顺序获取一个序号。序获取一个序号。(2) getComponent(int index)与与getComponent(int x,int y): 这两个方法分别获得指定序号或指定这两个方法分别获得指定序号或指定(x,y)坐标点处的组件。坐标点处的组件。(3) remove(Component)与与remove(int index): 将指定将指定的组件或指定序号的组件从容器中移出。的组件或指定序号的组件从容器中移出。(4) removeAll( ): 将容器中所有的组件移出。将容器中所有的组件移出。(5) setLayou

227、t( ): 设置容器的布局编辑器。设置容器的布局编辑器。Container可以引发可以引发ContainerEvent类代表的容器事类代表的容器事件。当容器中加入或移出一个组件时,容器将分别件。当容器中加入或移出一个组件时,容器将分别引发引发COMPONENT-ADDED和和COMPONENT-REMOVED两种容器事件。希望响应容器事件的程两种容器事件。希望响应容器事件的程序应该实现容器事件的监听者接口序应该实现容器事件的监听者接口ContainerListener,并在监听者内部具体实现该接,并在监听者内部具体实现该接口中用来处理容器事件的两个方法。口中用来处理容器事件的两个方法。 pub

228、lic void componentAdded(ContainerEvent e);/响应向容器中加入组件事件的方法响应向容器中加入组件事件的方法public void componentRemoved(ContainerEvent e);/响应从容器中移出组件的方法响应从容器中移出组件的方法 在这两个方法内部,可以调用实际参数在这两个方法内部,可以调用实际参数e的方法的方法e.getContainer( )获得引发事件的容器对象的引用,这个方法的返获得引发事件的容器对象的引用,这个方法的返回类型为回类型为Container;也可以调用;也可以调用e.getChild( )方法方法获得事件发生

229、时被加入或移出容器的组件,这个方获得事件发生时被加入或移出容器的组件,这个方法的返回类型为法的返回类型为Component。2. 容器事件容器事件(ContainerEvent)ContainerEvent类包含两个具体的与容器有关的事件:类包含两个具体的与容器有关的事件:(1) COMPONENT-ADDED: 把组件加入当前容器把组件加入当前容器对象。对象。(2) COMPONENT-REMOVED: 把组件移出当前容把组件移出当前容器对象。器对象。ContainerEvent类的主要方法有:类的主要方法有:(1) public Container getContainer( ): 返回引

230、发容器返回引发容器事件的容器对象。事件的容器对象。(2) public Component getChild( ): 返回引发容器事返回引发容器事件时被加入或移出的组件对象。件时被加入或移出的组件对象。3. PanelPanel属于无边框容器。无边框容器包括属于无边框容器。无边框容器包括Panel和和Applet,其中,其中Panel是是Container的子类,的子类,Applet是是Panel的子类。的子类。 Panel是最简单的容器,它没有边框或其他的可见的是最简单的容器,它没有边框或其他的可见的边界,它不能被移动、放大、缩小或关闭。一个程边界,它不能被移动、放大、缩小或关闭。一个程序不

231、能使用序不能使用Panel作为它的最外层的图形界面的容作为它的最外层的图形界面的容器,所以器,所以Panel总是作为一个容器组件被加入到其总是作为一个容器组件被加入到其他的容器,如他的容器,如Frame,Applet等中去。等中去。Panel也可以也可以进一步包含另一个进一步包含另一个Panel,使用,使用Panel的程序中总是的程序中总是存在着容器的嵌套。使用存在着容器的嵌套。使用Panel的目的通常是为了的目的通常是为了层次化管理图形界面的各个组件,同时使组件在容层次化管理图形界面的各个组件,同时使组件在容器中的布局操作更为方便。程序不能显式地指定器中的布局操作更为方便。程序不能显式地指定

232、Panel的大小,的大小,Panel的大小是由其中包含的所有组的大小是由其中包含的所有组件,以及包容它的那个容器的布局策略和该容器中件,以及包容它的那个容器的布局策略和该容器中的其他组件决定的。的其他组件决定的。例例 7-18 TestPanel.javaimport java.awt.*;import java.applet.*;import java.awt.event.*;public class TestPanel extends Applet implements ActionListener,ContainerListenerPanel p1,p2,p3;Label prompt1

233、,prompt2,prompt3;Button btn;public void init( ) p1 = new Panel( ); p1.setBackground(Color.gray); p2 = new Panel( ); p2.setBackground(Color.red); p3 = new Panel( ); p3.setBackground(Color.cyan); prompt1 = new Label(我在第一个我在第一个Panel里里); prompt2 = new Label(我在第二个我在第二个Panel里里); prompt3 = new Label(我在第三个我

234、在第三个Panel里里); btn = new Button(in Panel3); p1.add(prompt1); p2.add(prompt2); p3.add(prompt3); p3.add(btn); p1.add(p3); add(p1); add(p2); btn.addActionListener(this); p1.addContainerListener(this);public void actionPerformed(ActionEvent e) if(e.getSource( )=btn)p1.remove(p3);public void componentRemo

235、ved(ContainerEvent e) showStatus(您移去了第三个您移去了第三个Panel); public void componentAdded(ContainerEvent e)图图7.19是例是例7-18的运行结果。的运行结果。容器的嵌套是容器的嵌套是Java程序程序GUI界面设计和实现中经常需界面设计和实现中经常需要使用到的手段,实现这一类要使用到的手段,实现这一类GUI界面时,应该首界面时,应该首先明确各容器之间的包含嵌套关系。例如,例先明确各容器之间的包含嵌套关系。例如,例7-18中的程序中的程序GUI存在如下的包含层次关系存在如下的包含层次关系(图图7.20)。图

236、图 7.19 例例7-18的运行结果的运行结果图图 7.20 多容器图形界面的结构层次关系多容器图形界面的结构层次关系由于这个程序是一个由于这个程序是一个Java Applet,所以程序最外层,所以程序最外层的容器是一个的容器是一个Applet,其中包含了两个组件:第一,其中包含了两个组件:第一个组件是一个个组件是一个Panel对象对象p1;第二个组件是另一个;第二个组件是另一个Panel对象对象p2,p1中包含了一个标签中包含了一个标签prompt1和第三和第三个个Panel对象对象p3;p3中包含一个标签中包含一个标签prompt3和一个和一个按钮按钮btn。这里所有的容器都使用缺省的。这

237、里所有的容器都使用缺省的FlowLayout布局策略。布局策略。当用户单击按钮当用户单击按钮btn时,程序从时,程序从p1移去组件移去组件p3并引发并引发CONTAINER-REMOVED事件,程序响应这个事事件,程序响应这个事件后在状态条中显示移去组件容器的信息。件后在状态条中显示移去组件容器的信息。 Applet是一种特殊的是一种特殊的Panel,它是,它是Java Applet程序的程序的最外层容器,但是最外层容器,但是Java Applet并不是完整独立的程并不是完整独立的程序,它事实上是序,它事实上是WWW浏览器中的一个控件,是作浏览器中的一个控件,是作为浏览器的一部分依赖于浏览器而

238、存在的,所以为浏览器的一部分依赖于浏览器而存在的,所以Java Applet可以依赖浏览器的窗口来完成放大、缩可以依赖浏览器的窗口来完成放大、缩小、关闭等功能。至于小、关闭等功能。至于Java Applet程序本身,它只程序本身,它只要负责它所拥有的要负责它所拥有的Applet容器中的那部分无边框区容器中的那部分无边框区域就足够了。域就足够了。Applet容器的缺省布局策略与其父类容器的缺省布局策略与其父类Panel一致,都是一致,都是FlowLayout,但是,但是Applet容器中容器中还额外定义了一些用来与浏览器交互的方法,如还额外定义了一些用来与浏览器交互的方法,如init( ),st

239、art( ),stop( )等。等。 7.12 Frame与窗口事件与窗口事件 除除了了Applet和和Panel这这组组无无边边框框容容器器,Container还还有有一一组组有有边边框框的的容容器器的的子子类类,包包括括Window,Frame,Dialog和和FileDialog,其其中中Window是是所所有有有有边边框框容容器器的的父父类类,但但是是Window本本身身并并无无边边框框,算算是是有有边边框框容容器器的的一一个个例例外外。这这一一组组里里的的其其他他容容器器都都是是有有边框可独立存在的容器。边框可独立存在的容器。1. Frame在前面的例子中已经使用过在前面的例子中已经

240、使用过Frame这种容器,它是这种容器,它是Java中最重要、最常用的容器之一,是中最重要、最常用的容器之一,是Java Application程序的图形用户界面容器。程序的图形用户界面容器。Frame可以作为一个可以作为一个Application的最外层容器,也可的最外层容器,也可以被其他容器创建并弹出成为独立的容器,但是无以被其他容器创建并弹出成为独立的容器,但是无论哪种情况,论哪种情况,Frame都作为最顶层容器存在,不能都作为最顶层容器存在,不能被其他容器所包含。被其他容器所包含。 Frame有自己的外边框和自己的标题,创建有自己的外边框和自己的标题,创建Frame时时可以指定其窗口标

241、题。可以指定其窗口标题。 Frame(String title);也可以使用专门的方法也可以使用专门的方法getTitle( )和和setTitle(String)来来获取或指定获取或指定Frame的标题。新创建的的标题。新创建的Frame是不可是不可见的,需要使用见的,需要使用setVisible(boolean)方法,并使用实方法,并使用实际参数际参数true使之可见。使之可见。每个每个Frame在其右上角都有三个控制图标在其右上角都有三个控制图标(如图如图7.21所所示示),分别代表将窗口最小化、最大化和关闭的操,分别代表将窗口最小化、最大化和关闭的操作,其中最小化和最大化操作作,其中最

242、小化和最大化操作Frame可自动完成,可自动完成,而关闭窗口的操作不能通过点击关闭图标实现,需而关闭窗口的操作不能通过点击关闭图标实现,需要程序专门书写有关的代码。常用的关闭窗口的方要程序专门书写有关的代码。常用的关闭窗口的方法有三个:一个是设置一个按钮,当用户点击按钮法有三个:一个是设置一个按钮,当用户点击按钮时关闭窗口;第二个方法是对时关闭窗口;第二个方法是对WINDOWS-CLOSING事件做出响应,关闭窗口;第三个方法事件做出响应,关闭窗口;第三个方法是使用菜单命令。前一种方法需要专门的按钮,而是使用菜单命令。前一种方法需要专门的按钮,而后一种方法实现后一种方法实现WindowList

243、ener接口所需的代码较接口所需的代码较多,无论使用何种方法,都需要用到关闭多,无论使用何种方法,都需要用到关闭Frame的的dispose( )方法。方法。向向Frame窗口中添加和移出组件使用的方法与其他容窗口中添加和移出组件使用的方法与其他容器相同,也是器相同,也是add( )和和remove( ),Frame可以引发可以引发WindowEvent类代表的所有七种窗口事件。类代表的所有七种窗口事件。2. 窗口事件窗口事件(WindowEvent)WindowEvent类包含如下几个具体窗口事件。类包含如下几个具体窗口事件。(1) WINDOW-ACTIVATED:代表窗口被激活:代表窗口

244、被激活(在屏在屏幕的最前方待命幕的最前方待命)。(2) WINDOW-DEACTIVATED:代表窗口失活:代表窗口失活(其他其他窗口被激活后原活动窗口失活窗口被激活后原活动窗口失活)。(3) WINDOW-OPENED:代表窗口被打开。:代表窗口被打开。(4) WINDOW-CLOSED:代表窗口已被关闭:代表窗口已被关闭(指已关指已关闭后闭后)。(5) WINDOW-CLOSING:代表窗口正在被关闭:代表窗口正在被关闭(指指关闭前,如点击窗口的关闭按钮关闭前,如点击窗口的关闭按钮)。(6) WINDOW-ICONIFIED:代表使窗口最小化成图:代表使窗口最小化成图标。标。(7) WIN

245、DOW-DEICONIFIED:代表使窗口从图标:代表使窗口从图标恢复。恢复。WindowEvent类的主要方法有类的主要方法有public window getWindow( );此方法返回引发当前;此方法返回引发当前WindowEvent事件的具体事件的具体窗口,与窗口,与getSource( )方法返回的是相同的事件引用;方法返回的是相同的事件引用;但是但是getSource( )的返回类型为的返回类型为Object,而,而getWindow( )方法的返回值是具体的方法的返回值是具体的Window对象。对象。例例 7-19 TestFrame.java1: import java.aw

246、t.*;2: import java.awt.event.*;3:4: public class TestFrame 5: 6: public static void main(String args)7: 8: new MyFrame( );9: 10: 11: class MyFrame extends Frame implements ActionListener12: 13: Button btn;14: MyFrame( )15: 16: super(我的窗口我的窗口);17: btn = new Button(关闭关闭);18: setLayout(new FlowLayout(

247、);19: add(btn);20: btn.addActionListener(this);21: addWindowListener(new closeWin( );22: setSize(300,200);23: setVisible(true);24: 25: public void actionPerformed(ActionEvent e)26: 27: if(e.getActionCommand( )=关闭关闭)28: 29: dispose( );30: System.exit(0);31: 32: 33: 34: class closeWin extends WindowAd

248、apter35: 36: public void windowClosing(WindowEvent e) /监听到事件,关闭事件源窗口监听到事件,关闭事件源窗口37: 38: Frame frm = (Frame)(e.getSource( );39: frm.dispose( );40: System.exit(0);41: 42: 图图7.21是例是例7-19的运行结果。的运行结果。 图图 7.21 例例7-19的运行结果的运行结果 这是一个图形界面的这是一个图形界面的Java Application程序。程序里程序。程序里定义了三个类,定义了三个类,closeWin是窗口事件的剪裁类是

249、窗口事件的剪裁类WindowAdapter的子类,重载了的子类,重载了windowClosing( )方法来关闭被用户单击关闭图标按钮的事件源窗口。方法来关闭被用户单击关闭图标按钮的事件源窗口。MyFrame是用户定义的系统类是用户定义的系统类Frame的子类,里面的子类,里面包括一个按钮包括一个按钮btn,用户单击这个按钮时将关闭这,用户单击这个按钮时将关闭这个个MyFrame对象。主类对象。主类TestFrame的的main( )方法里方法里所创建的所创建的MyFrame的对象就是这个的对象就是这个Application的的图形界面窗口。图形界面窗口。7.13 菜单的定义与使用菜单的定义与

250、使用 关于关于Frame容器,还需要讨论的一点就是容器,还需要讨论的一点就是Frame是可是可以拥有菜单的容器,它实现了以拥有菜单的容器,它实现了MenuContainer接口。接口。菜单是非常重要的菜单是非常重要的GUI组件,每个菜单组件包括一组件,每个菜单组件包括一个菜单条,称为个菜单条,称为MenuBar。每个菜单条又包含若干。每个菜单条又包含若干个菜单项,称为个菜单项,称为Menu。每个菜单项再包含若干个。每个菜单项再包含若干个菜单子项,称为菜单子项,称为MenuItem。每个菜单子项的作用。每个菜单子项的作用与按钮相似,也是在用户点击时引发一个动作命令,与按钮相似,也是在用户点击时引

251、发一个动作命令,所以整个菜单就是一组经层次化组织、管理的命令所以整个菜单就是一组经层次化组织、管理的命令集合;使用它,用户可以方便地向程序发布指令。集合;使用它,用户可以方便地向程序发布指令。参看下面的例参看下面的例7-20。例例 7-20 TestMenu.java1: import java.awt.*;2: import java.awt.event.*;3:4: public class TestMenu /定义主类定义主类5: 6: public static void main(String args)7: 8: MyMenuFrame mf = new MyMenuFrame(

252、);9: mf.setSize(new Dimension(300,200); /用用setSize( )方法指定窗口的初始大小方法指定窗口的初始大小10: mf.setVisible(true); /使窗口可见使窗口可见11: 12:13:14: class MyMenuFrame extends Frame 15: implements ActionListener,ItemListener/定义定义窗口窗口16: 17: MenuBar m-MenuBar;18: Menu menuFile,menuEdit,m-Edit-Paste;19: MenuItem mi-File-Open,

253、mi-File-Close,mi-File-Exit,mi-Edit-Copy;20: MenuItem pi-New,pi-Del,pi-Pro,mi-Paste-All,mi-Paste-Part;21: CheckboxMenuItem mi-Edit-Cut;22: PopupMenu popM;23: TextArea ta;24:25: MyMenuFrame( ) /构造函数构造函数26: 27: super(拥有菜单的窗口拥有菜单的窗口); /指定窗口标题指定窗口标题28: ta = new TextArea(nnnnnnttt没有选择没有选择,5,20);29: ta.add

254、MouseListener(new HandleMouse(this); /文本域响应鼠标事件文本域响应鼠标事件30: add(Center,ta);31:32: popM = new PopupMenu( ); /创建弹出窗口创建弹出窗口33: pi-New = new MenuItem( 新建新建 ); /为弹出窗口创建菜单子项为弹出窗口创建菜单子项34: pi-New.addActionListener(this); /使菜单子项响应动作事件使菜单子项响应动作事件35: popM.add(pi-New); /为弹出菜单加入菜单子项为弹出菜单加入菜单子项36: pi-Del = new M

255、enuItem( 删除删除 );37: pi-Del.addActionListener(this);38: popM.add(pi-Del);39: pi-Pro = new MenuItem( 属性属性 );40: pi-Pro.addActionListener(this);41: popM.add(pi-Pro);42: ta.add(popM); /将弹出窗口加在文本域上将弹出窗口加在文本域上43: 44: m-MenuBar = new MenuBar( );/创建菜单条创建菜单条45: 46: menuFile = new Menu(文件文件); /创建菜单项,创建菜单子项并指定

256、快捷键创建菜单项,创建菜单子项并指定快捷键47: mi-File-Open = new MenuItem(打开打开,new MenuShortcut(o);48: mi-File-Close = new MenuItem(关闭关闭);49: mi-File-Exit = new MenuItem(退出退出);50: mi-File-Exit.setShortcut(new MenuShortcut(x); /设置菜单子项的快捷键设置菜单子项的快捷键51: mi-File-Open.setActionCommand(打开打开); /再设置命令名再设置命令名52: mi-File-Exit.set

257、ActionCommand(退出退出); /以便动作响应程序调用以便动作响应程序调用53: mi-File-Open.addActionListener(this); /使菜单子项响应动作事件使菜单子项响应动作事件54: mi-File-Close.addActionListener(this);55: mi-File-Exit.addActionListener(this);56: menuFile.add(mi-File-Open); /把菜单子项加入菜单项把菜单子项加入菜单项57: menuFile.add(mi-File-Close);58: menuFile.addSeparator

258、( ); /加一条横向分割线加一条横向分割线59: menuFile.add(mi-File-Exit);60: m-MenuBar.add(menuFile); /把菜单项加入菜单条把菜单项加入菜单条61: 62: menuEdit = new Menu(编辑编辑);63: mi-Edit-Copy = new MenuItem(复制复制);64: mi-Edit-Cut = new CheckboxMenuItem(剪切剪切); /创建选择菜单子项创建选择菜单子项65: m-Edit-Paste = new Menu(粘贴粘贴);/创建二级菜单项创建二级菜单项66: mi-Paste-Al

259、l = new MenuItem(全部粘贴全部粘贴);67: mi-Paste-Part = new MenuItem(部分粘贴部分粘贴);68: mi-Edit-Copy.addActionListener(this);69: mi-Edit-Cut.addItemListener(this);/检测盒菜单子项产生选择事件检测盒菜单子项产生选择事件70: m-Edit-Paste.add(mi-Paste-Part); /为二级菜单项加入菜单子项为二级菜单项加入菜单子项71: m-Edit-Paste.add(mi-Paste-All);72: mi-Paste-Part.addAction

260、Listener(this);73: mi-Paste-All.addActionListener(this);74: menuEdit.add(mi-Edit-Copy);75: menuEdit.add(mi-Edit-Cut);76: menuEdit.addSeparator( );77: menuEdit.add(m-Edit-Paste); /把二级菜单项加入菜单项把二级菜单项加入菜单项78: m-MenuBar.add(menuEdit);79:80: this.setMenuBar(m-MenuBar); /把菜单条加入整个把菜单条加入整个Frame容器容器81: 82: pu

261、blic void actionPerformed(ActionEvent e) /响应动作事件响应动作事件83: 84: if(e.getActionCommand( )=退出退出)/选择选择退出退出菜单则关闭窗口退出程序菜单则关闭窗口退出程序85: 86: dispose( );87: System.exit(0);88: 89: else /否则显示选择的命令名否则显示选择的命令名90: ta.setText(nnnnnnttt+e.getActionCommand( );91: 92: public void itemStateChanged(ItemEvent e) /响应响应Che

262、ckboxMenuItem单击事件单击事件93: 94: if(e.getSource( )=mi-Edit-Cut)95: if(CheckboxMenuItem)e.getSource( ).getState( )/查看是否选中查看是否选中96: ta.setText(nnnnnnttt+选择了选择了 /因为无命令名,所以用标签因为无命令名,所以用标签97: +(CheckboxMenuItem)e.getSource( ).getLabel( );98: else99: ta.setText(nnnnnnttt+未选择未选择100: +(CheckboxMenuItem)e.getSou

263、rce( ).getLabel( );101: 102: 103:104: class HandleMouse extends MouseAdapter/处理鼠标事件类,继承鼠标事件裁剪类处理鼠标事件类,继承鼠标事件裁剪类105: 106: MyMenuFrame m-Parent;/产生事件的组件所在的窗口容器产生事件的组件所在的窗口容器107: 108: HandleMouse(MyMenuFrame mf)/构造函数构造函数109: 110: m-Parent = mf;111: 112: public void mouseReleased(MouseEvent e)/鼠标按键鼠标按键松

264、开事件弹出菜单松开事件弹出菜单113: 114: if(e.isPopupTrigger( ) /检查鼠标事件是否是由弹检查鼠标事件是否是由弹出菜单引发的出菜单引发的115: m-Parent.popM.show(Component)e.getSource( ),e.getX( ),e.getY( );116: /将弹出菜单显示在用户鼠标点击的位置将弹出菜单显示在用户鼠标点击的位置117: 例例7-20使用了使用了Java中提供的大部分关于菜单的功能,中提供的大部分关于菜单的功能,Java中的菜单分为两大类:一类是菜单条式菜单,中的菜单分为两大类:一类是菜单条式菜单,通常称的菜单就是指这类菜单

265、;另一类是弹出式菜通常称的菜单就是指这类菜单;另一类是弹出式菜单。下面先讨论菜单条式菜单的实现与使用。单。下面先讨论菜单条式菜单的实现与使用。1. 菜单的设计与实现菜单的设计与实现菜单的设计与实现步骤如下:菜单的设计与实现步骤如下:(1) 创建菜单条创建菜单条MenuBar。例如下面的语句创建了一。例如下面的语句创建了一个空的菜单条。个空的菜单条。 m-MenuBar = new MenuBar( ); (2) 创建不同的菜单项创建不同的菜单项Menu加入到空菜单条中。下面加入到空菜单条中。下面的语句创建了一个菜单项并把它加入到菜单条中,的语句创建了一个菜单项并把它加入到菜单条中,菜单项的标题

266、为菜单项的标题为“编辑编辑”。 menuEdit = new Menu(编辑编辑); m-MenuBar.add(menuEdit);(3) 为每个菜单项创建其所包含的更小的菜单子项为每个菜单项创建其所包含的更小的菜单子项MenuItem,并把菜单子项加入到菜单项中去。,并把菜单子项加入到菜单项中去。 mi-Edit-Copy = new MenuItem(复制复制); menuEdit.add(mi-Edit-Copy); (4) 将整个建成的菜单条加入到某个容器中去。将整个建成的菜单条加入到某个容器中去。this.setMenuBar(m-MenuBar);这里的这里的this代表程序的容

267、器代表程序的容器Frame,需要注意的是,需要注意的是并非每个容器都可以配菜单条式菜单,只有实现了并非每个容器都可以配菜单条式菜单,只有实现了MenuContainer接口的容器才能加入菜单。接口的容器才能加入菜单。(5) 上面的这些工作主要是为了组建菜单的结构,如上面的这些工作主要是为了组建菜单的结构,如有哪些菜单项,哪些菜单子项,等,但如何定义各有哪些菜单项,哪些菜单子项,等,但如何定义各个菜单子项所对应的命令和操作呢?首先要将各菜个菜单子项所对应的命令和操作呢?首先要将各菜单子项注册给实现了动作事件的监听接口单子项注册给实现了动作事件的监听接口ActionListener的监听者,如,例

268、的监听者,如,例7-20中的容器。中的容器。mi-Edit-Copy.addActionListener(this); (6) 为监听者定义为监听者定义actionPerformed(ActionEvent e)方方法,在这个方法中调用法,在这个方法中调用e.getSource( )或或e.getActionCommand( )来判断用户点击的菜单子项,并完成这个子项定来判断用户点击的菜单子项,并完成这个子项定义的操作。义的操作。创建好的菜单条式菜单位于窗口的上方,图创建好的菜单条式菜单位于窗口的上方,图7.22就显就显示了例示了例7-20中创建的菜单条中创建的菜单条 。 图图 7.22 拥有

269、菜单条的拥有菜单条的Frame窗口窗口2. 使用分隔线使用分隔线有时希望在菜单子项之间增加一条横向分隔线,以便有时希望在菜单子项之间增加一条横向分隔线,以便把菜单子项分成几组。加入分隔线的方法是把菜单子项分成几组。加入分隔线的方法是Menu的方法的方法addSeparator( ),使用时要注意该语句的位,使用时要注意该语句的位置。菜单子项是按照加入的先后顺序排列在菜单项置。菜单子项是按照加入的先后顺序排列在菜单项中的,希望把分隔线加在哪里,就要把分隔线语句中的,希望把分隔线加在哪里,就要把分隔线语句放在哪里。例如,在放在哪里。例如,在“文件文件”菜单项中用如下的语菜单项中用如下的语句加入了一

270、条分隔线句加入了一条分隔线(参看图参看图7.22)。menuFile.addSeparator( ); /加一条横向分隔线加一条横向分隔线 3. 使用菜单子项快捷键使用菜单子项快捷键除了用鼠标选择菜单子项,还可以为每个菜单子项定除了用鼠标选择菜单子项,还可以为每个菜单子项定义一个键盘快捷键,这样用键盘一样可以选择菜单义一个键盘快捷键,这样用键盘一样可以选择菜单子项。快捷键是一个字母,定义好后按住子项。快捷键是一个字母,定义好后按住Ctrl键和键和这个字母就可以选中对应的菜单子项。为菜单子项这个字母就可以选中对应的菜单子项。为菜单子项定义快捷键有两种方法:一种是在创建菜单子项的定义快捷键有两种方

271、法:一种是在创建菜单子项的同时定义快捷键。同时定义快捷键。MenuItem mi-File-Open = new MenuItem(打开打开,new MenuShortcut(o); 另一种是为已经存在的菜单子项定义快捷键。另一种是为已经存在的菜单子项定义快捷键。mi-File-Exit.setShortcut(new MenuShortcut(x); /单独设置菜单子项的快捷键单独设置菜单子项的快捷键设置后菜单子项设置后菜单子项“打开打开”对应快捷键对应快捷键Ctrl+O,菜单,菜单子项子项“退出退出”对应对应Ctrl+X,参见图,参见图7.22。 4. 使用二级菜单使用二级菜单如果希望菜单

272、子项还能够进一步再引出更多的菜单项,如果希望菜单子项还能够进一步再引出更多的菜单项,可以使用二级菜单。二级菜单的使用方法很简单,可以使用二级菜单。二级菜单的使用方法很简单,创建一个包含若干菜单子项创建一个包含若干菜单子项(MenuItem)的菜单项的菜单项(Menu),把这个菜单项像菜单子项一样加入到一级,把这个菜单项像菜单子项一样加入到一级菜单项中即可。菜单项中即可。m-Edit-Paste = new Menu(粘贴粘贴); /创建二级菜单项创建二级菜单项mi-past-All = new MenuItem(全部粘贴全部粘贴);mi-past-Part = new MenuItem(部分粘

273、贴部分粘贴);m-Edit-Paste.add(mi-Paste-Part); /为二级菜单项加入菜单为二级菜单项加入菜单子项子项m-Edit-Paste.add(mi-Paste-All);menuEdit.add(m-Edit-Paste); /把二级菜单项加入菜单项把二级菜单项加入菜单项 二级菜单的使用效果如图二级菜单的使用效果如图7.23所示。所示。 图图 7.23 二级菜单与检测盒菜单子项二级菜单与检测盒菜单子项 5. 使用检测盒菜单子项使用检测盒菜单子项Java中还定义了一种特殊的菜单子项,称为检测盒菜中还定义了一种特殊的菜单子项,称为检测盒菜单子项单子项CheckboxMenuI

274、tem。这种菜单子项与检测。这种菜单子项与检测盒一样,有盒一样,有“选中选中”和和“未选中未选中”两种状态,每次两种状态,每次选择这类菜单子项都使它在这两种状态之间切换,选择这类菜单子项都使它在这两种状态之间切换,处于处于“选中选中”状态的检测盒菜单子项的前面有一个状态的检测盒菜单子项的前面有一个小对号小对号(如图如图7.23所示所示),处于,处于“未选中未选中”状态时没状态时没有这个小对号。有这个小对号。创建检测盒菜单子项并把它加入菜单项的方法为:创建检测盒菜单子项并把它加入菜单项的方法为:mi-Edit-Cut = new CheckboxMenuItem(剪切剪切);/创建选择创建选择菜

275、单子项菜单子项menuEdit.add(mi-Edit-Cut); 选择检测盒菜单子项引发的事件不是动作事件选择检测盒菜单子项引发的事件不是动作事件ActionEvent,而是选择事件,而是选择事件ItemEvent,所以需要,所以需要把检测盒菜单子项注册给把检测盒菜单子项注册给ItemListener,并具体实,并具体实现现ItemListener的的itemStateChanged(ItemEvent e)事件,与响应检测盒的事件较为相似。事件,与响应检测盒的事件较为相似。 mi-Edit-Cut.addItemListener(this); 6. 使用弹出式菜单使用弹出式菜单弹出式菜单附

276、着在某一个组件或容器上,一般它是不弹出式菜单附着在某一个组件或容器上,一般它是不可见的,只有当用户用鼠标右键点击附着有弹出式可见的,只有当用户用鼠标右键点击附着有弹出式菜单的组件时,这个菜单才菜单的组件时,这个菜单才“弹出弹出”来显示。来显示。弹出式菜单与菜单条式菜单一样,也包含若干个菜单弹出式菜单与菜单条式菜单一样,也包含若干个菜单子项,创建弹出式菜单并加入菜单子项的操作如下:子项,创建弹出式菜单并加入菜单子项的操作如下:PopupMenu popM = new PopupMenu( );/创建弹出窗口创建弹出窗口MenuItem pi-New = new MenuItem( 新建新建 );

277、 /为弹出窗口创建菜单子项为弹出窗口创建菜单子项pi-New.addActionListener(this); /使菜单子项响应动作事件使菜单子项响应动作事件popM.add(pi-New); /为弹出菜单加入菜单子项为弹出菜单加入菜单子项然后需要把弹出式菜单附着在某个组件或容器上。然后需要把弹出式菜单附着在某个组件或容器上。ta.add(popM); /将弹出窗口加在文本域上将弹出窗口加在文本域上用户点击鼠标右键时弹出式菜单不会自动显示出来,还用户点击鼠标右键时弹出式菜单不会自动显示出来,还需要一定的程序处理,首先把附着有弹出菜单的组件需要一定的程序处理,首先把附着有弹出菜单的组件或容器注册

278、给或容器注册给MouseListener。ta.addMouseListener(new HandleMouse(this);/文本域响应鼠标事件,弹出菜单文本域响应鼠标事件,弹出菜单然后重载然后重载MouseListener的的mouseReleased(MouseEvent e)方法。在这个方法里调方法。在这个方法里调用弹出式菜单的方法用弹出式菜单的方法show( )把它自身显示在用户鼠标把它自身显示在用户鼠标点击的位置。点击的位置。 public void mouseReleased(MouseEvent e)/鼠标按键松开事件弹出菜单鼠标按键松开事件弹出菜单if(e.isPopupTr

279、igger( ) /检查鼠标事件是否由弹出菜单引发检查鼠标事件是否由弹出菜单引发m-Parent.popM.show(Component)e.getSource( ),e.getX( ),e.getY( ); /将弹出菜单显示在用户鼠标点击的位置将弹出菜单显示在用户鼠标点击的位置这里方法这里方法e.getSource( )返回的是附着有弹出式菜单的返回的是附着有弹出式菜单的组件或容器,弹出式菜单应该显示在这个组件或容组件或容器,弹出式菜单应该显示在这个组件或容器中鼠标点击的位置器中鼠标点击的位置(由由e.getX( )方法和方法和e.getY( )方方法确定鼠标点击的坐标位置法确定鼠标点击的坐

280、标位置),如图,如图7.24所示。所示。 图图 7.24 弹出式菜单的显示与使用弹出式菜单的显示与使用7.14 对话框、组件事件与焦点事件对话框、组件事件与焦点事件1. 组件事件组件事件(ComponentEvent)这个类是所有低级事件的根类,一共包含四个具体事这个类是所有低级事件的根类,一共包含四个具体事件,可以用件,可以用ComponentEvent类的几个静态常量来类的几个静态常量来表示。表示。(1) ComponentEvent.COMPONENT-HIDDEN:代表:代表隐藏组件的事件。隐藏组件的事件。(2) ComponentEvent.COMPONENT-SHOWN:代表:代表

281、显示组件的事件。显示组件的事件。(3) ComponentEvent.COMPONENT-MOVED:代表:代表移动组件的事件。移动组件的事件。(4) ComponentEvent.COMPONENT-RESIZED:代:代表改变组件大小的事件。表改变组件大小的事件。把调用把调用getID( )方法的返回值与上述常量相比较,就方法的返回值与上述常量相比较,就可以知道可以知道ComponentEvent对象所代表的具体事件。对象所代表的具体事件。2. 焦点事件焦点事件(FocusEvent)FocusEvent类包含两个具体事件,分别对应这个类的类包含两个具体事件,分别对应这个类的两个同名静态整

282、型常量。两个同名静态整型常量。(1) FOCUS-GAINED:代表获得了注意的焦点。:代表获得了注意的焦点。(2) FOCUS-LOST:代表失去了注意的焦点。:代表失去了注意的焦点。一个一个GUI的对象必须首先获得注意的焦点,才能被进的对象必须首先获得注意的焦点,才能被进一步操作。例如,一个文本输入区域必须首先获得一步操作。例如,一个文本输入区域必须首先获得注意的焦点,才能接受用户键入的文字。一个窗口注意的焦点,才能接受用户键入的文字。一个窗口只有先获得了注意的焦点,其中的菜单才能被选中只有先获得了注意的焦点,其中的菜单才能被选中等。获得注意的焦点将使对象被调到整个屏幕的最等。获得注意的焦

283、点将使对象被调到整个屏幕的最前面并处于待命的状态,是缺省操作的目标对象,前面并处于待命的状态,是缺省操作的目标对象,而失去注意焦点的对象则被调到屏幕的后面并可能而失去注意焦点的对象则被调到屏幕的后面并可能被其他的对象遮挡。被其他的对象遮挡。3. 对话框对话框(Dialog)与与Frame一样,一样,Dialog是有边框、有标题的独立存在是有边框、有标题的独立存在的容器,并且不能被其他容器所包容;但是的容器,并且不能被其他容器所包容;但是Dialog不能作为程序的最外层容器,也不能包含菜单条。不能作为程序的最外层容器,也不能包含菜单条。与与Window一样,一样,Dialog必须隶属于一个必须隶

284、属于一个Frame并由并由这个这个Frame负责弹出。负责弹出。Dialog通常起到与用户交互通常起到与用户交互的对话框的作用,例如向用户报告消息并要求确认的对话框的作用,例如向用户报告消息并要求确认的消息对话框,接受用户输入的一般对话框等。的消息对话框,接受用户输入的一般对话框等。 Dialog的构造函数有四种重载方式,其中最复杂的为:的构造函数有四种重载方式,其中最复杂的为:Dialog(Frame parent, String title, boolean isModal) 第一个参数指明新创建的第一个参数指明新创建的Dialog对话框隶属于哪个对话框隶属于哪个Frame窗口,第二个参数

285、指明新建窗口,第二个参数指明新建Dialog对话框的对话框的标题,第三个参数指明该对话框是否是有模式的。标题,第三个参数指明该对话框是否是有模式的。所谓所谓“有模式有模式”的对话框,是那种一旦打开后用户的对话框,是那种一旦打开后用户必须对其做出响应的对话框,例如对话框询问用户必须对其做出响应的对话框,例如对话框询问用户是否确认删除操作,此时程序处于暂停状态,除非是否确认删除操作,此时程序处于暂停状态,除非用户回答了对话框的问题,否则是不能使用程序的用户回答了对话框的问题,否则是不能使用程序的其他部分的,所以带有一定的强制性质;而无模式其他部分的,所以带有一定的强制性质;而无模式对话框则没有这种

286、限制,用户完全可以不理会这个对话框则没有这种限制,用户完全可以不理会这个打开的对话框而去操作程序的其他部分,缺省情况打开的对话框而去操作程序的其他部分,缺省情况下对话框都是无模式的。新建的对话框使用缺省的下对话框都是无模式的。新建的对话框使用缺省的BorderLayout,它是不可见的,可以使用,它是不可见的,可以使用show( )方方法显示它。法显示它。 对于已经创建的对话框,还可以用对于已经创建的对话框,还可以用setModal(boolean isModal)方法来改变其模式属性,或者使用方法来改变其模式属性,或者使用boolean isModal( )方法来判断它是否是一个有模式对话框

287、。另外,方法来判断它是否是一个有模式对话框。另外,Dialog还有获得和修改其对话框标题的方法还有获得和修改其对话框标题的方法getTitle( )和和setTitle(String newTitle);还有加入和移出组;还有加入和移出组件的方法件的方法add(Component)和和remove(Component)。先来看一个用先来看一个用Dialog实现的消息对话框和一般对话框实现的消息对话框和一般对话框的例子。的例子。 例例 7-21 TestDialog.java1: import java.awt.*;2: import java.awt.event.*;3:4: public c

288、lass TestDialog /定义定义Java Application主类主类5: 6: public static void main(String args)7: 8: MyDialogFrame df = new MyDialogFrame( );9: 10: 11:12: class MyDialogFrame extends Frame 13: implements ActionListener,ComponentListener,FocusListener14: 15: Dialog MegDlg,InOutDlg; /对话框隶属于对话框隶属于Frame16: Button b

289、tn1,btn2,btnY,btnN,btnR;17: TextField tf = new TextField(没有信息没有信息,45);18: TextField getMeg = new TextField(输入信息输入信息,10);19:20: MyDialogFrame( ) /构造函数构造函数21: 22: super(使用对话框使用对话框);23: btn1 = new Button(隐藏隐藏);24: btn2 = new Button(询问询问); 25: btnY = new Button(是是);26: btnN = new Button(否否);27: btnR = n

290、ew Button(返回返回);28: setLayout(new FlowLayout( );29: add(tf); 30: add(btn1); 31: add(btn2);32: btn1.addComponentListener(this);33: this.addWindowListener(new WinAdpt( ); /Frame响应窗口关闭事件响应窗口关闭事件34: btn1.addActionListener(this); 35: btn2.addActionListener(this);36: btnY.addActionListener(this); 37: btnN

291、.addActionListener(this); 38: btnR.addActionListener(this);39: setSize(350,150); /改变改变Frame尺寸尺寸40: show( ); /显示原来不可见的显示原来不可见的Frame41: 42: public void actionPerformed(ActionEvent e) /响应按钮引发的动作事件响应按钮引发的动作事件43: 44: if(e.getActionCommand( )=隐藏隐藏) /按按“隐藏隐藏”按钮将隐藏此按钮本身按钮将隐藏此按钮本身45: /创建创建有模式有模式的消息对话框向用户确认删除

292、操的消息对话框向用户确认删除操作作46: MegDlg = new Dialog(this,真要隐藏吗?真要隐藏吗?,true);47: Panel p1 = new Panel( );48: p1.add(new Label(此操作将隐藏该按钮,要此操作将隐藏该按钮,要继续吗?继续吗?);49: MegDlg.add(Center,p1);50: Panel p2 = new Panel( );51: p2.add(btnY);52: p2.add(btnN);53: MegDlg.add(South,p2);54: MegDlg.setSize(200,100);55: MegDlg.sh

293、ow( );/显示对话框显示对话框56: 57: else if(e.getActionCommand( )=询问询问) 58: /创建创建无模式无模式的对话框接受用户输入的信息的对话框接受用户输入的信息59: InOutDlg = new Dialog(this,请输入信息请输入信息);60: InOutDlg.add(Center,getMeg);61: InOutDlg.add(South,btnR);62: InOutDlg.setSize(200,100);63: InOutDlg.addFocusListener(this);64: InOutDlg.show( );65: 66:

294、 else if(e.getActionCommand( )=是是) /用户对消息对话框中的按钮的响应用户对消息对话框中的按钮的响应67: 68: MegDlg.dispose( ); /关闭消息对话框关闭消息对话框69: btn1.setVisible(false); /确认隐藏,引发组件事件确认隐藏,引发组件事件70: 71: else if(e.getActionCommand( )=否否) /用户对用户对 消息对话框中的按钮的响应消息对话框中的按钮的响应72: MegDlg.dispose( ); /取消隐藏操作,取消隐藏操作, 关闭对话框关闭对话框73: else if(e.getA

295、ctionCommand( )=返回返回)/用户用户对输入输出对话框中按钮的响应对输入输出对话框中按钮的响应74: /获取用户在对话框的输入并显示在获取用户在对话框的输入并显示在Frame中中75: tf.setText(getMeg.getText( )+是对话框的输入是对话框的输入); 76: InOutDlg.dispose( );/关闭输入输出对话框关闭输入输出对话框77: 78: 79: public void componentShown(ComponentEvent e)/实现实现ComponentListener中方法中方法80: public void componentRe

296、sized(ComponentEvent e)81: public void componentMoved(ComponentEvent e)82: public void componentHidden(ComponentEvent e) /当按钮被隐藏时,显示相关信息当按钮被隐藏时,显示相关信息83: 84: tf.setText(按钮按钮+(Button)e.getComponent( ).getLabel( )+被隐藏!被隐藏!);85: 86: public void focusGained(FocusEvent e)87: 88: getMeg.setText(对话框对话框+(Di

297、alog)e.getComponent( ).getTitle( )89: +获得了注意的焦点!获得了注意的焦点!);90: 91: public void focusLost(FocusEvent e) 92: 93: class WinAdpt extends WindowAdapter /创建窗口剪裁类子类,处理窗口关闭事件创建窗口剪裁类子类,处理窗口关闭事件94: 95: public void windowClosing(WindowEvent e)96: 97: (Frame)e.getWindow( ).dispose( ); /获得引发事件的窗口并关闭之获得引发事件的窗口并关闭

298、之98: System.exit(0);99: 100: 这个程序的最外层容器是一个这个程序的最外层容器是一个Frame窗口,它可以响窗口,它可以响应动作事件和容器事件。窗口中包含一个文本框和应动作事件和容器事件。窗口中包含一个文本框和两个按钮。用户点击第一个按钮两个按钮。用户点击第一个按钮“隐藏隐藏”时,弹出时,弹出消息对话框消息对话框MegDlg。其中包含一个。其中包含一个Label询问用户询问用户是否确实要隐藏第一个按钮,还包含两个按钮是否确实要隐藏第一个按钮,还包含两个按钮“是是”和和“否否”。如果用户按。如果用户按“否否”,则关闭此对话框;,则关闭此对话框;如果按如果按“是是”,则关

299、闭对话框并隐藏第一个按钮,则关闭对话框并隐藏第一个按钮,此时隐藏按钮的操作将引发组件事件把相关信息显此时隐藏按钮的操作将引发组件事件把相关信息显示在示在Frame的文本框的文本框tf中。中。用户点击用户点击Frame的第二个按钮的第二个按钮“询问询问”时,弹出输入时,弹出输入输出对话框输出对话框InOutDlg,请用户在这个对话框的文本,请用户在这个对话框的文本框中输入信息。框中输入信息。InOutDlg对话框可以响应获得注意对话框可以响应获得注意焦点的事件,当用户输入并按焦点的事件,当用户输入并按“返回返回”按钮时,关按钮时,关闭此对话框并把其文本框闭此对话框并把其文本框getMeg中的信息

300、传送回中的信息传送回Frame的文本框的文本框tf显示。程序运行结果如图显示。程序运行结果如图7.25所示。所示。 Dialog 还有一个子类还有一个子类FileDialog,用来表示一种特殊,用来表示一种特殊的用来搜索目录和文件,并打开或保存特定文件的的用来搜索目录和文件,并打开或保存特定文件的对话框,将在后面结合对话框,将在后面结合Java的文件操作介绍的文件操作介绍FileDialog的使用方法。的使用方法。图图 7.25 例例7-21的运行结果的运行结果 7.15 小结小结本章介绍图形用户界面的本章介绍图形用户界面的Java编程方法,主要介绍编程方法,主要介绍java.awt和和jav

301、a.awt.event两个包的使用。两个包的使用。7.1节概述节概述了图形用户界面的基础知识,主要包括图形界面的了图形用户界面的基础知识,主要包括图形界面的构成。构成。7.2节介绍了图形界面中用户自定义成分的绘节介绍了图形界面中用户自定义成分的绘制,包括绘制图形,显示文字和图像,控制颜色以制,包括绘制图形,显示文字和图像,控制颜色以及实现动画效果等。及实现动画效果等。7.3节介绍节介绍Java的委托事件处理的委托事件处理机制的基本原理,机制的基本原理,7.4节简述节简述java.awt包中的标准包中的标准GUI组件。从组件。从7.5节开始详细介绍每种组件的创建、节开始详细介绍每种组件的创建、使

302、用与事件处理,包括文本框、文本区域、各种选使用与事件处理,包括文本框、文本区域、各种选择组件、滚动条和按钮等。择组件、滚动条和按钮等。7.10节介绍节介绍Java的常用的常用布局策略。布局策略。7.11节到节到7.14节介绍了节介绍了Java的主要容器的主要容器组件,包括组件,包括Panel,Frame,Dialog等。等。习题习题7-1 什么是图形用户界面?它与字符界面有何不同?什么是图形用户界面?它与字符界面有何不同?你是否曾使用过这两种界面?试列举出图形用户界你是否曾使用过这两种界面?试列举出图形用户界面中你使用过的组件。面中你使用过的组件。7-2 简述图形界面的构成成分,它们各自的作用

303、。设简述图形界面的构成成分,它们各自的作用。设计和实现图形用户界面的工作主要有哪两个?计和实现图形用户界面的工作主要有哪两个?7-3 Java程序的图形用户界面中有哪些用户自定义成程序的图形用户界面中有哪些用户自定义成分?分?7-4 编写编写Applet程序,画出一条螺旋线。程序,画出一条螺旋线。7-5 编写编写Applet程序,用程序,用paint( )方法显示一行字符串,方法显示一行字符串,Applet包含两个按钮包含两个按钮“放大放大”和和“缩小缩小”,当用户,当用户单击单击“放大放大”时显示的字符串字体放大一号,单击时显示的字符串字体放大一号,单击“缩小缩小”时显示的字符串字体缩小一号

304、。时显示的字符串字体缩小一号。7-6 编写编写Applet程序,包含三个标签,其背景分别为程序,包含三个标签,其背景分别为红、黄、蓝三色。红、黄、蓝三色。7-7 改写例改写例7-4,让用户输入欲显示,让用户输入欲显示.gif文件名,程序文件名,程序将这个图像文件加载到内存并显示。将这个图像文件加载到内存并显示。7-8 改写例改写例7-5,在,在Applet中增加两个按钮中增加两个按钮“左旋左旋”和和“右旋右旋”,用户单击这两个按钮时动画中的图像向,用户单击这两个按钮时动画中的图像向相应的方向旋转。相应的方向旋转。 7-9 简述简述Java的事件处理机制和委托事件模型。什么的事件处理机制和委托事

305、件模型。什么是事件源?什么是监听者?是事件源?什么是监听者?Java的图形用户界面中,的图形用户界面中,谁可以充当事件源?谁可以充当监听者?谁可以充当事件源?谁可以充当监听者?7-10 列举列举java.awt.event包中定义的事件类,并写出包中定义的事件类,并写出它们的继承关系。它们的继承关系。7-11 列举列举GUI的各种标准组件和它们之间的层次继承的各种标准组件和它们之间的层次继承关系。使用标准组件的基本步骤是什么?关系。使用标准组件的基本步骤是什么?7-12 Component类有何特殊之处?其中定义了哪些类有何特殊之处?其中定义了哪些常用方法?常用方法?7-13 将各种常用组件的

306、创建语句、常用方法、可能将各种常用组件的创建语句、常用方法、可能引发的事件、需要注册的监听者和监听者需要重载引发的事件、需要注册的监听者和监听者需要重载的方法综合在一张表格中画出。的方法综合在一张表格中画出。 7-14 动作事件的事件源可以有哪些?如何响应动作动作事件的事件源可以有哪些?如何响应动作事件?事件?7-15 编写编写Applet包括一个标签、一个文本框和一个按包括一个标签、一个文本框和一个按钮,当用户单击按钮时,程序把文本框中的内容复钮,当用户单击按钮时,程序把文本框中的内容复制到标签中。制到标签中。7-16 文本框与文本区域在创建方法、常用方法和事文本框与文本区域在创建方法、常用

307、方法和事件响应上有何异同?什么操作将引发文本事件?如件响应上有何异同?什么操作将引发文本事件?如何响应文本事件?编写何响应文本事件?编写Applet包含一个文本框、一包含一个文本框、一个文本区域和一个按钮,当用户单击按钮时,程序个文本区域和一个按钮,当用户单击按钮时,程序将文本区域中被选中的字符串复制到文本框中。将文本区域中被选中的字符串复制到文本框中。7-17 什么是选择事件?哪些操作将引发选择事件?什么是选择事件?哪些操作将引发选择事件?可能产生选择事件的可能产生选择事件的GUI组件有哪些?它们之间有组件有哪些?它们之间有什么异同?分别适合于什么场合?什么异同?分别适合于什么场合? 7-1

308、8 将例将例7-8、7-9、7-10综合成一个程序,使用综合成一个程序,使用Checkbox标志按钮的背景色,使用标志按钮的背景色,使用CheckboxGroup标志三种字体风格,使用标志三种字体风格,使用Choice选选择字号,使用择字号,使用List选择字体名称,由用户确定按钮选择字体名称,由用户确定按钮的背景色和前景字符的显示效果。的背景色和前景字符的显示效果。7-19 什么是调整事件?调整事件与选择事件有何不什么是调整事件?调整事件与选择事件有何不同?什么是滚动条?如何创建和使用滚动条?编写同?什么是滚动条?如何创建和使用滚动条?编写一个一个Applet包含一个滚动条,在包含一个滚动条

309、,在Applet中绘制一个中绘制一个圆,用滚动条滑块显示的数字表示该圆的直径,当圆,用滚动条滑块显示的数字表示该圆的直径,当用户拖动滑块时,圆的大小随之改变。用户拖动滑块时,圆的大小随之改变。7-20 编写一个编写一个Applet响应鼠标事件,用户可以通过拖响应鼠标事件,用户可以通过拖动鼠标在动鼠标在Applet中画出矩形,并在状态条显示鼠标中画出矩形,并在状态条显示鼠标当前的位置。当前的位置。7-21 改写改写7-20题,使用一个题,使用一个Vector对象保存用户所画对象保存用户所画过的每个矩形并显示、响应键盘事件,当用户击键过的每个矩形并显示、响应键盘事件,当用户击键q时清除屏幕上所有的

310、矩形。时清除屏幕上所有的矩形。7-22 改写改写7-18题的程序,使用一个题的程序,使用一个Canvas及其上的及其上的字符串,来显示各选择组件确定的显示效果。字符串,来显示各选择组件确定的显示效果。7-23 什么是容器的布局策略?试列举并简述什么是容器的布局策略?试列举并简述Java中中常用的几种布局策略。常用的几种布局策略。7-24 编写编写Applet程序实现一个计算器,包括十个数字程序实现一个计算器,包括十个数字(09)按钮和四个运算符按钮和四个运算符(加、减、乘、除加、减、乘、除)按钮,按钮,以及等号和清空两个辅助按钮,还有一个显示输入以及等号和清空两个辅助按钮,还有一个显示输入输出

311、的文本框。试分别用输出的文本框。试分别用BorderLayout和和GridLayout实现。实现。7-25 Panel与与Applet有何关系?有何关系?Panel在在Java程序里通程序里通常起到什么作用?常起到什么作用?7-26 为什么说为什么说Frame是非常重要的容器?为什么使用是非常重要的容器?为什么使用Frame的程序通常要实现的程序通常要实现WindowListener?关闭?关闭Frame有哪些方法?有哪些方法?7-27 将将7-15题改写为图形界面的题改写为图形界面的Application程序。程序。7-28 利用利用Canvas对象,将对象,将7-19题的程序改写为图形题

312、的程序改写为图形界面的界面的Application程序。程序。7-29 常用的菜单有哪两类?是不是任何容器都可以常用的菜单有哪两类?是不是任何容器都可以使用菜单?简述实现菜单的编程步骤。使用菜单?简述实现菜单的编程步骤。 7-30 编写图形界面的编写图形界面的Application程序,包含一个菜程序,包含一个菜单,选择这个菜单的单,选择这个菜单的“退出退出”选项可以关闭选项可以关闭Application的窗口并结束程序。的窗口并结束程序。7-31 扩充扩充7-30题的程序,使题的程序,使Application窗口中包含一窗口中包含一个文本区域和一个按钮,文本区域中事先包含一段个文本区域和一个按钮,文本区域中事先包含一段文字,利用焦点监听者和文本监听者实现如下功能:文字,利用焦点监听者和文本监听者实现如下功能:当用户修改了文本框中的内容并试图离开这个文本当用户修改了文本框中的内容并试图离开这个文本框时,程序弹出有模式对话框请用户确认修改;如框时,程序弹出有模式对话框请用户确认修改;如果用户只是进入并退出文本框而没有修改其中的内果用户只是进入并退出文本框而没有修改其中的内容,则不会弹出对话框。容,则不会弹出对话框。7-32 根据本章的所学习的内容用根据本章的所学习的内容用Java Application编编写一个模拟的文字编辑器。写一个模拟的文字编辑器。

展开阅读全文
相关资源
正为您匹配相似的精品文档
相关搜索

最新文档


当前位置:首页 > 高等教育 > 研究生课件

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号