• 沒有找到結果。

Java语言程序设计案例教程 - 万水书苑-出版资源网

N/A
N/A
Protected

Academic year: 2021

Share "Java语言程序设计案例教程 - 万水书苑-出版资源网"

Copied!
50
0
0

加載中.... (立即查看全文)

全文

(1)第4章. 图形用户界面设计. 图形用户界面为用户和程序的友好交互提供了一种机制,是软件开发的一项非 常重要的工作。本章将详细介绍如何使用 Java 语言编写图形界面,通过引导一步一 步创建图形界面程序,读者不需要深入了解每一步骤的原理,只要能按照步骤创建 程序即可。通过示例程序的学习,了解创建示例程序的过程,对图形界面有一个总 体的认识。.           . 图形用户界面概述 Applet 类 HTML 文件参数传递 Java 绘图、字体及颜色处理 框架与面板 按钮、标签、文本框与文本区域 事件处理机制 布局设计 菜单设计 对话框设计 常用 Swing 组件简介. 4.1. 图形用户界面概述. 在传统的操作系统 MS-DOS 文字模式下,屏幕上显示的是单调的文字,使用者必须通过 键盘输入指令才能操作计算机。图形用户界面或图形用户接口(Graphical User Interface,GUI) 是指采用图形方式,借助菜单、按钮等标准界面元素,用户可以通过鼠标等外设向计算机系统 发出指令、启动操作,并将系统运行的结果同样以图形方式显示给用户的技术。GUI 是事件 驱动的,常见交互包括移动鼠标、单击鼠标按钮、在文字段输入、从菜单选择一个选项以及关 闭一个窗口等。随着操作系统向图形化方向的发展,各种编程语言也随之纷纷实现 GUI 接口, 支持用户的 GUI 编程。下面对 Java 语言的 GUI 发展作一简介。 在 Java 1.0 刚问世时,包含一个用于基本 GUI 程序设计的类库,Sun 将它称为抽象窗口工 具箱(Abstract Window Toolkit,AWT)。AWT 库将处理用户界面元素的任务委派给每个目标 平台(Windows、Solaris、Macintosh 等)的本地 GUI 工具箱,由本地 GUI 工具箱负责用户界.

(2) 第 4 章 图形用户界面设计. 面元素的创建和操作。从理论上说,程序可以运行在任何平台上,其体验(look and feel)的 效果依赖于目标平台,当时,Sun 公司的口号是“一次编写,到处运行”。但遗憾的是,使用 AWT 构建的 GUI 应用程序看起来没有 Windows 或 Macintosh 应用程序显示得那么漂亮,也没 有提供那些平台用户所熟悉的功能。更为糟糕的是,在不同平台上的 AWT 用户界面库中存在 着不同的 bug,研发人员必须在每一个平台上测试他们的应用程序,因此人们嘲弄 AWT 为“一 次编写,到处调试”。目前,AWT 已基本淘汰。 从 Java 1.2 版开始,Sun 公司推出了新的图形界面工具包:Swing。Swing 的本意是“秋千, 摇摆”等意思,和图形用户界面之间没有任何关系,实际上,它是 Sun 公司在开发这个新的 图形用户界面项目的工程代号,并无特别含义。相应的工具包都以 Swing 来命名,例如 javax.swing、javax.swing.event。相对 AWT 而言,Swing 更为轻便,更容易编程,而且功能也 更为灵活、强大,是 Java 基础类(Java Foundation Classes,JFC)的主要组成部分,它包括以 下几个部分: (1)Swing 组件:提供了图形界面所需的所有组件,从框架、对话框直到按钮、标签等。 (2)界面风格:可以让 GUI 程序选择不同的风格,比如 Java 风格、Mac 风格、Windows 风格等,每种风格的外观都不一样。 (3)辅助技术:可以让辅助阅读器顺利读取信息。 (4)Java 2D 编程接口:让开发人员方便地产生高质量的二维平面文字、图形和图像。 (5)拖放支持:提供了 Java 程序和本机系统应用程序之间的拖放支持。 当 Eclipse.org 社区人员开始构建 Eclipse 时,他们意识到 Swing 和 AWT 都存在不足,他们决 定构建一套新的 GUI 开发工具包,用来显示 Eclipse 界面。这个工具包借用了 VisualAge SmallTalk 中的大量的库。他们把这个新的工具包命名为 SWT(Standard Widget Toolkit) 。意识到本地行为需 要本地窗口部件,SWT 的设计者们采用了 AWT 的对等架构,而仅仅当本地组件不存在时(例如 Motif 下的树形组件) ,才求助于 Java 实现。这样,SWT 吸收了 AWT 和 Swing 实现的最好的部分: 当可以得到本地组件时使用本地实现,当不能得到本地组件时使用 Java 实现。这就同时保证了与 本地窗口部件相当的外观和响应度。SWT 于 2001 年与 Eclipse IDE(Integrated Development Environment)一起集成发布。带有本地操作系统观感的 UI 组件如图 4.1 所示。. 图 4.1 本地操作系统观感的 UI 组件. 虽然 SWT 很强大,但它比较底层,一些功能在使用上较低级,不太符合面向对象的特征。 因此,在 SWT 的基础上又开发了 JFace。JFace 在 SWT 上进行了一定的扩展,它提供了 SWT 的功能和更简易的 MVC 模式。SWT 使用直接的 API 提供了原生的窗口部件,例如,创建一 个 table 部件并且插入想显示的行和列的数据。JFace 则提供了在 SWT 基础之上的抽象层,所 以可以对抽象层编程,然后抽象层与 SWT API 交互来替代直接对 SWT API 编程。 SWT 和 JFace 代表了 Java 在 GUI 上的最新方向,有兴趣的读者可以通过网络,对此作更 深入的了解。. 69.

(3) 70. Java 语言程序设计案例教程. 4.2 Applet 类 Java Applet 是用 Java 语言编写的一些小应用程序,这些程序是直接嵌入到页面中,可以 由支持 Java 的浏览器解释执行或用 appletviewer 来运行,或在支持 Java 的浏览器上运行。它 可以大大提高 Web 页面的交互能力和动态执行能力,人机交互友好,同时还能处理图像、声 音、动画等多媒体数据。 当用户访问这样的网页时,Applet 被下载到用户的计算机上执行,由于 Applet 是在用户 的计算机上执行的,所以它的执行速度不受网络带宽的限制,用户可以更好地欣赏网页上 Applet 产生的多媒体效果。 Applet 小应用程序的实现主要依靠 java.applet 包中的 Applet 类。与一般的应用程序不同, Applet 应用程序必须嵌入在 HTML 页面中,才能得到解释执行;同时 Applet 可以从 Web 页面 中获得参数,并和 Web 页面进行交互。 4.2.1 Applet 类 Applet 类是所有 Applet 应用的基类,所有的 Java 小应用程序都必须继承该类。如下所示: import java. applet.*; public class OurApplet extends Applet { ...... ...... }. Applet 类的构造函数只有一种,即:public Applet()。 4.2.2 建立 Applet 小应用程序 如下例所示。 【例 4.1】用 Applet 小应用程序输出字符串“hello world”。 import java.applet.*; import java.awt.*; public class MyApplet extends Applet { String s; public void init() { s = "hello world"; } public void paint(Graphics g) { g.drawString(s, 70, 80); } }. Eclipse 界面如图 4.2 所示。 在 Eclipse 中运行,采取如下方法: 右击源文件,在弹出菜单中选择“Run As”/“Java Applet”,如图 4.3 所示。.

(4) 第 4 章 图形用户界面设计. 图 4.2 建立 Applet 小应用程序. 图 4.3 在 Eclipse 中运行 Applet 小程序. 小程序查看器界面如图 4.4 所示。. 图 4.4 小程序查看器运行界面. 71.

(5) 72. Java 语言程序设计案例教程. 注意. 在 Eclipse 中运行时可能会出现如下的警告: 警告:不能读取 appletviewer 的属性文件: C:\Documents and Settings\Administrator\.hotjava\properties 使用默认值。 解决方法如下: (1)打开命令提示窗口。 (2)输入 PolicyTool 并按 Enter 键。 (3)在规则工具对话框中,单击添加规则项目按钮。 (4)单击“Add Permission”按钮(添加权限)。 (5)单击许可下拉菜单,选择“All Permission”。 (6)单击“Ok”(确认)。 (7)单击“Done”(完成)。 (8)从“File”菜单中选择“Save as”。 (9)在 C:\Documents and Settings\Administrator(当前操作系统用户名)\中保 存.java.policy 文件(这个要根据情况来 如果没有.java.policy 文件,开始会弹出个 提示说是在什么地方找不到.java.policy,就把它存在提示的那个目录下面) 。. 也可以在 DOS 窗口(命令提示符下)中编译运行 Applet 小应用程序,步骤如下: (1)建立 MyApplet.java 源文件。 (2)编译源文件,在 DOS 窗口(命令提示符下)中运行 javac MyApplet.java,如果没有 错误,编译后会生成 MyApplet.class 字节码文件。 (3)建立一个 html 文件 testApplet.html,内容如下: <html> <applet code=MyApplet.class width=200 height=200> </applet> </html>. (4)在 DOS 窗口中运行 appletviewer testApplet.html。 4.2.3 Applet 的生命周期 Applet 根据执行过程中发生的事件来定义其生命周期,如图 4.5 所示,对于每个事件将自 动调用一种方法,方法如下: (1)init()方法 这个方法主要是为 Applet 的正常运行做一些初始化工作。当一个 Applet 被系统调用时, 系统首先自动调用该方法,只执行一次。通常可以在该方法中完成从网页向 Applet 传递参数, 添加用户界面的基本组件等操作。 (2)start()方法 系统在调用完 init()方法之后,将自动调用 start()方法。而且,每当用户离开包含该 Applet 的主页后又再返回时,系统又会再执行一遍 start()方法。这就意味着 start()方法可以被多次执 行,而不像 init()方法。因此,可把只希望执行一次的代码放在 init()方法中。可以在 start()方 法中开始一个线程,如继续一个动画、声音等。 (3)stop()方法.

(6) 第 4 章 图形用户界面设计. 图 4.5 Applet 的生命周期. 这个方法在用户离开 Applet 所在页面时执行,因此,它也是可以被多次执行的。它可以 在用户并不注意 Applet 的时候,停止一些耗用系统资源的工作,以免影响系统的运行速度, 且并不需要人为地去调用该方法。如果 Applet 中不包含动画、声音等程序,通常也不必实现 该方法。 (4)destroy()方法 与对象的 finalize()方法不同,Java 在浏览器关闭的时候才调用该方法。Applet 是嵌在 HTML 文件中的,所以 destroy()方法不关心何时 Applet 被关闭,它在浏览器关闭的时候自动 执行。在 destroy()方法中一般可以要求收回占用的非内存独立资源。如果在 Applet 仍在运行 时浏览器被关闭,系统将先执行 stop()方法,再执行 destroy()方法。 需要注意的是 paint()方法虽不在生命周期内,但它的作用却是 Applet 的灵魂。 在网页中与用户的动态交互是 Java 吸引人的原因之一,用户可以通过鼠标或键盘与 Java Applet 程序对话。下面通过一个例子来演示 Applet 对鼠标和键盘响应,要注意的是 Java 并不 区分鼠标的左右键。 【例 4.2】用 Applet 演示分别对鼠标和键盘按下、松开的响应示例。 import java.awt.*; import java.applet.*; public class MouseAndKeyBord extends Applet { String text=""; public void paint(Graphics g) { g.drawString(text,20,20); } public boolean mouseDown(Event evt,int x,int y) { text="Mouse Down"; repaint(); return true; }. //鼠标按下处理函数. 73.

(7) 74. Java 语言程序设计案例教程 public boolean mouseUp(Event evt,int x,int y) { text=""; repaint(); return true; } public boolean keyDown(Event evt,int x) { text="Key Down"; repaint(); return true; } public boolean keyUp(Event evt,int x) { text=""; repaint(); return true; }. //鼠标松开处理函数. //键盘被按下的处理函数. //键盘被松开的处理函数. }. 4.2.4 Applet 类常用方法 Applet 类常用方法如下: (1)public boolean isActive(); 判断一个 Applet 是否处于活动状态。 (2)public URL getDocumentBase(); 检索表示该 Applet 运行的文件目录的对象。 (3)public URL getCodeBase(); 获取该 Applet 代码的 URL 地址。 (4)public String getParameter(String name); 获取该 Applet 由 name 指定参数的值。 (5)public AppletContext getAppletContext(); 返回浏览器或小应用程序观察器。 (6)public void resize(int width,int height); 调整 Applet 运行的窗口尺寸。 (7)public void resize(Dimension d); 调整 Applet 运行的窗口尺寸。 (8)public void showStatus(String msg); 在浏览器的状态条中显示指定的信息。 (9)public Image getImage(URL url); 按 url 指定的地址装入图像。 (10)public Image getImage(URL url,String name); 按 url 指定的地址和文件名加载图像。 (11)public AudioClip getAudioClip(URL url); 按 url 指定的地址获取声音文件。.

(8) 第 4 章 图形用户界面设计. (12)public AudioClip getAudioClip(URL url, String name); 按 url 指定的地址和文件名获取声音。 (13)public String getAppletInfo(); 返回 Applet 应用有关的作者、版本和版权方面的信息。 (14)public String [][]getParameterInfo(); 返回描述 Applet 参数的字符串数组,该数组通常包含三个字符串:参数名、该参数所需 值的类型和该参数的说明。 (15)public void play(URL url); 加载并播放一个 url 指定的音频剪辑。 (16)public void destroy(); 撤消 Applet 及其所占用的资源。若该 Applet 是活动的,则先终止该 Applet 的运行。. 4.3. HTML 文件参数传递. HTML 是超文本标记语言,它通过各种各样的标记来编排超文本信息。在 HTML 文档中 嵌入 Applet 同样需要使用一组约定好的特殊标记。如<APPLET>和</APPLET>是嵌入 Applet 的标记,其中至少需包括三个参数:code、height 和 width。在<APPLET>标记中还可以使用其 他一些可选的参数。利用 Applet 可以接收从 HTML 中传递过来的参数,下面对这些参数作一 简单说明。 1.CODE 标志 CODE 标志指定 Applet 的类名;WIDTH 和 HEIGHT 标志指定 Applet 窗口的像素尺寸。 在 APPLET 语句里还可使用其他一些标志。 2.CODEBASE 标志 CODEBASE 标志指定 Applet 的 URL 地址。Applet 的通用资源定位地址 URL,它可以是 绝 对 地 址 , 如 www.sun.com。 也 可 以 是 相 对 于 当 前 HTML 所 在 目 录 的 相 对 地 址 , 如 /AppletPath/Name。如果 HTML 文件不指定 CODEBASE 标志,浏览器将使用和 HTML 文件 相同的 URL。 3.ALT 标志 虽然 Java 在 WWW 上很受欢迎,但并非所有浏览器都对其提供支持。如果某浏览器无法 运行 Java Applet,那么它在遇到 APPLET 语句时将显示 ALT 标志指定的文本信息。 4.ALIGN 标志 ALIGN 标 志 可 用 来 控 制 把 Applet 窗 口 显 示 在 HTML 文 档 窗 口 的 什 么 位 置 。 与 HTML<LMG>语句一样,ALIGN 标志指定的值可以是 TOP、MIDDLE 或 BOTTOM。 5.VSPACE 与 HSPACE 标志 VSPACE 和 HSPACE 标志指定浏览器显示在 Applet 窗口周围的水平和竖直空白条的尺寸, 单位为像素。 6.NAME 标志 NAME 标志把指定的名字赋予 Applet 的当前实例。当浏览器同时运行两个或多个 Applet 时,各 Applet 可通过名字相互引用或交换信息。如果忽略 NAME 标志,Applet 的名字将对应 于其类名。. 75.

(9) 76. Java 语言程序设计案例教程. 7.PARAM 标志 通用性是程序设计所追求的目标之一。使用户或者程序员能很方便地使用同一个 Applet 完成不同的任务是通用性的具体表现。从 HTML 文件获取信息是提高 Applet 通用性的一条有 效途径。 假设编制了一个把某公司的名字在屏幕上卷动的 Applet。为了使该 Applet 更加通用,则 可以使该 Applet 从 HTML 文件获取需要卷动的文本信息。这样,若想显示另一个公司的名字, 用不着修改 Java Applet 本身,只需修改 HTML 文件即可。 PARAM 标志可用来在 HTML 文件里指定参数,格式如下所示: PARAM Name="name" Value="Liter". Java Applet 可调用 getParameter()方法获取 HTML 文件里设置的参数值。 Applet 的下载与图形文件一样需要一定的时间,若干秒后它才能在屏幕上显示出来。等待 的时间则取决于 Applet 的大小和用户的网络连接的速度。一旦下载以后,它便和本地计算机 上的程序以相同的速度运行了。 Applet 在用户的计算机上执行时,还可以下载其他的资源,如声音文件、图像文件或更多 的 Java 代码,有些 Applet 还允许用户进行交互式操作。但这需要重复的链接与下载,因此速 度很慢,这是一个亟待解决的问题,可以想到的一个好办法是采用类似高速缓存的技术,将每 次下载的文件都临时保存在用户的硬盘上,虽然第一次使用时花的时间比较多,但当再次使用 时,只需直接从硬盘上读取文件而无需再与 Internet 连接,便可以大大提高性能了。 【例 4.3】根据从 Web 页中得到的 str 参数值(成绩等级),输出对应的分数段。 import java.awt.Graphics; import java.applet.Applet; public class Grade extends Applet { String str,score; public void init() { str=getParameter("str"); if(str.equals("及格")) score="60~70"; else if(str.equals("中")) score="70~80"; else if(str.equals("良")) score="80~90"; else if(str.equals("优")) score="90~100"; } public void paint(Graphics g) { g.drawString(str +":"+score,10,25); }. //得到 Web 页中的 str 参数的值. //输出分数段. }. 请注意 init()方法中的 str=getParameter("str")这条语句,它可以取得通过网页传过来的参 数,该参数名称为 str,现在编写 HTML 文件,通过该文件向 Applet 传递参数。 <HTML>.

(10) 第 4 章 图形用户界面设计 <HEAD>在 HTML 中传递 Applet 使用的字符串参数</HEAD> <HR> <BODY> <APPLET CODE="Grade.class" WIDTH=150 HEIGHT=30> <PARAM NAME="str" VALUE="及格"> </APPLET> <BR><HR> <APPLET CODE="Grade.class" WIDTH=150 HEIGHT=30> <PARAM NAME="str" VALUE="中"> </APPLET> <BR><HR> <APPLET CODE="Grade.class" WIDTH=150 HEIGHT=30> <PARAM NAME="str" VALUE="良"> </APPLET> <BR><HR> <APPLET CODE="Grade.class" WIDTH=150 HEIGHT=30> <PARAM NAME="str" VALUE="优"> </APPLET> </BODY> </HTML>. 注意加粗的代码,这些参数夹在<APPLET>和</APPLET>之间,每个参数包含在尖括号中, 以 PARAM 标记开头,参数名称在“NAME=”中给出,参数值在“VALUE=”中给出,参数 值都是字符串。 程序运行结果如图 4.6 所示。. 图 4.6 例 4.3 程序运行结果. 4.4. Java 绘图、字体及颜色处理. 4.4.1 Java 绘图 Java 在图形处理方面有丰富的类库和方法,使用这些方法可以便捷地绘图,基本的绘图方 法包括点、线、矩形和圆等。绘制这些图形要用到 AWT 中的 Graphics 类,它常用的方法如下:. 77.

(11) 78. Java 语言程序设计案例教程. (1)drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) 绘制一个覆盖指定矩形的圆弧或椭圆弧边框。 (2)drawLine(int x1, int y1, int x2, int y2) 在此图形上下文的坐标系统中,使用当前颜色在点 (x1, y1) 和 (x2, y2) 之间画一条线。 (3)drawOval(int x, int y, int width, int height) 绘制椭圆的边框。 (4)drawPolygon(int[] xPoints, int[] yPoints, int nPoints) 绘制一个由 x 和 y 坐标数组定义的闭合多边形。 (5)drawPolygon(Polygon p) 绘制由指定的 Polygon 对象定义的多边形边框。 (6)drawPolyline(int[] xPoints, int[] yPoints, int nPoints) 绘制由 x 和 y 坐标数组定义的一系列连接线。 (7)drawRect(int x, int y, int width, int height) 绘制指定矩形的边框。 (8)drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) 用此图形上下文的当前颜色绘制圆角矩形的边框。 (9)drawString(AttributedCharacterIterator iterator, int x, int y) 使用此图形上下文的当前颜色绘制由指定迭代器给定的文本。 (10)drawString(String str, int x, int y) 使用此图形上下文的当前字体和颜色绘制由指定 string 给定的文本。 (11)fill3DRect(int x, int y, int width, int height, boolean raised) 绘制一个用当前颜色填充的 3-D 突出显示矩形。 (12)fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) 填充覆盖指定矩形的圆弧或椭圆弧。 (13)fillOval(int x, int y, int width, int height) 使用当前颜色填充外接指定矩形框的椭圆。 (14)fillPolygon(int[] xPoints, int[] yPoints, int nPoints) 填充由 x 和 y 坐标数组定义的闭合多边形。 (15)fillPolygon(Polygon p) 用图形上下文的当前颜色填充由指定的 Polygon 对象定义的多边形。 (16)fillRect(int x, int y, int width, int height) 填充指定的矩形。 (17)fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) 用当前颜色填充指定的圆角矩形。 (18)getClip() 获取当前的剪贴区域。 (19)getClipBounds() 返回当前剪贴区域的边界矩形。 (20)getClipBounds(Rectangle r) 返回当前剪贴区域的边界矩形。.

(12) 第 4 章 图形用户界面设计. (21)getColor() 获取此图形上下文的当前颜色。 (22)getFont() 获取当前字体。 (23)getFontMetrics() 获取当前字体的字体规格。 (24)getFontMetrics(Font f) 获取指定字体的字体规格。 (25)hitClip(int x, int y, int width, int height) 如果指定的矩形区域与当前的剪贴区域相交,则返回 true。 (26)setClip(int x, int y, int width, int height) 将当前的剪贴区设置为由给定坐标指定的矩形。 (27)setClip(Shape clip) 将当前的剪贴区域设置为任意的剪贴形状。 (28)setColor(Color c) 将此图形上下文的当前颜色设置为指定颜色。 (29)setFont(Font font) 将此图形上下文的字体设置为指定字体。 (30)setPaintMode() 设置此图形上下文的绘图模式,以便通过此图形上下文中的当前颜色来改写目标。 (31)setXORMode(Color c1) 将此图形上下文的绘图模式设置为在此图形上下文的当前颜色和新的指定颜色之间交 替。 (32)toString() 返回表示此 Graphics 对象值的 String 对象。 (33)translate(int x, int y) 将图形上下文的原点平移到当前坐标系统中的点(x, y)。 Java 中的任何一个图形组件,小到文本框、标签,大到一个框架、一个对话框,都有一 个专门负责显示其界面的方法,这个方法名称是固定的:paint(),它的原型为: public void paint(Graphics g) { …… }. 每当组件大小、位置、组件内容发生变化时,该方法即负责生成新的图形界面显示。由 于该方法可以被子类继承,因此,继承的子类有能力修改该方法。如果子类中没有出现该方法, 表示其行为完全继承自父类,则不管组件中是否添加了新的内容,是否发生了大小的改变,是 否发生了位移,父类都要有一个专门的线程,来负责描绘变化以后的组件界面。paint 方法由 父类自动维护,如果子类一旦重载该方法,必须自己去维护所有的界面显示。 在 Java 中提供了一套丰富的工具——AWT,用来实现容易实现的、平台独立的图形用户 接口。它主要由组件(components)、容器(containers)和布局管理器(layouts)三部分组成, 通过事件来表达和处理程序、系统和用户之间的动作与关系。. 79.

(13) 80. Java 语言程序设计案例教程. 1.画直线 void drawLine(int startX,int startY,int endX,int endY);. 四个参数分别为:起始点的 x 坐标和 y 坐标以及终点的 x 坐标和 y 坐标,该方法用于在 起点(startX,startY)和终点(endX,endY)之间画一条直线。坐标参数是相对的,它们相对于 左上角的坐标为(0,0),以像素为单位,向右向下延伸,直线如果超出窗口,则超出的部分不 会显示,如图 4.7 所示。 X. 0,0 x1,y1. x2,y2. Y 图 4.7 画直线. 【例 4.4】画直线示例。 //DrawLine.java import java.awt.*; import java.applet.*; public class DrawLine extends Applet { public void paint(Graphics g) { //从点(0,0)到点(400,400)之间画直线 g.drawLine(0,0,400,400); //从点(0,400)到点(400,0)之间画直线 g.drawLine(0,400,400,0); } }. 2.画矩形 Java 提供了三种画矩形的方式: (1)画直角矩形 void drawRect(int x,int y,int width,int height);. 绘制一个左上角坐标为(x,y),宽为 width,高为 height 的直角矩形。 void fillRect(int x,int y,int width,int height);. 绘制一个左上角坐标为(x,y),宽为 width,高为 height 的有填充效果的直角矩形。 【例 4.5】画矩形示例。 //DrawRect.java.

(14) 第 4 章 图形用户界面设计 import java.awt.*; import java.applet.*; public class DrawRect extends Applet { public void paint(Graphics g) { g.drawRect(20,20,100,160); g.fillRect(200,20,100,160); } }. (2)画圆角矩形 void drawRoundRect(int x,int y,int width,int height,int arcWidth,int arcHeight);. 绘制一个左上角坐标为(x,y),宽为 width,高为 height,在 x 轴方向上圆边半径为 arcWidth, 在 y 轴方向上圆边半径为 arcHeight 的圆角矩形。 void fillRoundRect(int x,int y,int width,int height,int arcWidth,int arcHeight);. 绘制一个左上角坐标为(x,y),宽为 width,高为 height,在 x 轴方向上圆边半径为 arcWidth, 在 y 轴方向上圆边半径为 arcHeight 的有填充效果的圆角矩形。 【例 4.6】画圆角矩形示例。 //DrawRoundRect.java import java.awt.*; import java.applet.*; public class DrawRoundRect extends Applet { public void paint(Graphics g) { g.drawRoundRect(20,20,100,160,20,20); g.fillRoundRect(200,20,100,160,20,20); } }. (3)画阴影三维矩形 【例 4.7】画三维矩形示例。 //Draw3DRect.java import java.awt.*; import java.applet.*; public class Draw3DRect extends Applet { public void paint(Graphics g) { //设置亮灰色颜色,主要是 3D 效果用此颜色可以比较清楚地看出来 g.setColor(Color.lightGray); g.draw3DRect(20,20,100,160,true); g.draw3DRect(200,20,100,160,false); } }. 3.画圆和椭圆 void drawOval(int x,int y,int width,int height); void fillOval(int x,int y,int width,int height);. 上述两种方法在坐标为(x,y)处,绘制或者填充一个长轴为 width,短轴为 height 的椭圆。当 长轴 width 与短轴 height 相等时,椭圆就变成了圆,所以 Java 并没有专门提供绘制圆的方法。 【例 4.8】画椭圆和圆示例。 //DrawEllipse.java import java.awt.*; import java.applet.*; public class DrawEllipse extends Applet {. 81.

(15) 82. Java 语言程序设计案例教程 public void paint(Graphics g) { //在原点为(10,10),半径为 50 画圆 g.drawOval(10,10,50,50); //在原点为(100,10),半径为 50 画填充效果的圆 g.fillOval(100,10,50,50); //在原点为(190,10),长轴为 90,短轴为 30 画椭圆 g.drawOval(190,10,90,30); //在原点为(70,90),长轴为 140,短轴为 100 画填充效果的椭圆 g.fillOval(70,90,140,100); } }. 4.画弧 void drawArc(int x,int y,int width,int height,int startAngle,int endAngle); void fillArc(int x,int y,int width,int height,int startAngle,int endAngle);. 弧的绘制方法有 6 个参数:起始 x 坐标和 y 坐标,边界椭圆的长和宽,开始画弧的角度 startAngle 和终止画弧前扫过的角度 endAngle。前 4 个参数确定了弧的尺寸和形状,后 2 个参 数确定弧的端点(起止角度),其值为正表示逆时针方向,为负表示顺时针方向。 【例 4.9】画弧示例。 //DrawArc.java import java.awt.*; import java.applet.*; public class DrawArc extends Applet { public void paint(Graphics g) { // 在原点为(10,40),半径为 70,起始角度为 0 度,逆时针转 90 度的圆弧 g.drawArc(10, 40, 70, 70, 0, 90); // 在原点为(100,40),半径为 70,起始角度为 0 度,逆时针转 90 度的圆弧 g.fillArc(100, 40, 70, 70, 0, 90); // 在原点为(10,100),长轴为 80,短轴为 70,起始角度为 0 度,顺时针转 90 度的弧 g.drawArc(10, 100, 70, 80, 0, -90); // 在原点为(100,100),长轴为 80,短轴为 70,起始角度为 0 度,顺时针转 90 度的填充弧 g.fillArc(100, 100, 70, 80, 0, -90); } }. 5.画多边形 多边形是不限边数的图形,而这些边实际上是由一组点连接而成的,所以绘制多边形需 要一组(x,y)坐标对。绘图的原理是从第一个(x,y)坐标对开始,向第二个坐标对画一条直线,然 后向第三个(x,y)坐标对画一条直线,依次类推,可以画出多边形。下面有四个方法绘制和填充 多边形: void drawPloygon(int []xPoints,int []yPoints,int numPoints); void drawPloygon(Polygon polygon); void fillPloygon(int []xPoints,int []yPoints,int numPoints); void filldrawPloygon(Polygon polygon);. xPoints 代表 x 坐标的整型数组,yPoints 代表 y 坐标的整型数组,numPoints 代表所有点 数的整数,当然,x 数组和 y 数组应该具有相同数目的元素。通过规定 Polygon 对象或者 x、y 数组值来设置多边形的点。如果起始点和终点不重合,上述的绘图方法自动将多边形封闭。如 果希望绘制一系列相连的直线,不需要自动封闭图形,可以使用 drawPolyLine()方法。 【例 4.10】画多边形示例。.

(16) 第 4 章 图形用户界面设计 //DrawPolygon.java import java.awt.*; import java.applet.*; public class DrawPolygon extends Applet { public void paint(Graphics g) { int xArr[] = { 78,188,194,284,106,116,52 }; int yArr[] = { 66,148,72,140,216,160,212 }; //获得(x,y)坐标对数组的长度 int numPoints=xArr.length; g.drawPolygon( xArr, yArr, numPoints); } }. 4.4.2 Java 字体类 一个 Font 类的对象表示了一种字体显示效果,包括字体类型、字型和字号。下面的语句 用于创建一个 Font 类的对象: Font MyFont = new Font ("TimesRoman", Font.BOLD, 12 );. MyFont 对应的是 12 磅 TimesRoman 类型的黑体字,其中指定字型时需要用到 Font 类的 三个常量:Font.PLAIN、Font.BOLD、Font.ITALIC。 Font 类的构造方法如下: public Font (java.lang.String name, int style, int size). 说明: name:本地可获取的字体名称。 style:表示字体样式,包含 Font.PLAIN、Font.BOLD、Font.ITALIC 三种,分别对应普通 体、加粗和斜体。 size:字体的大小。 示例: int style = Font.BOLD; Font font = new Font ("Garamond", style , 11);. 可采用一个实用的方法来获取本地可用字体: 注意. GraphicsEnvironment ge=GraphicsEnvironment.getLocalGraphicsEnvironment(); String[] fa=ge.getAvailableFontFamilyNames();. 这样,通过从绘图环境中获取到本地可用的字体名数组。 程序指定的字体取决于系统所安装的字体库,如果系统中没有指定的字体的话,Java 会 用默认的字体(通常是 Courier 字体)来代替。可以利用在 java.awt.ToolKit 类中提供的 getFontList()方法得到当前系统中可用字体库的列表。 【例 4.11】用不同字体绘制字符串。 //DrawText.java import java.awt.*; import java.applet.*; public class DrawText extends Applet { public void paint(Graphics g) { // 创建四个字体对象 Font f1 = new Font("TimesRoman", Font.PLAIN, 18); Font f2 = new Font("TimesRoman", Font.BOLD, 20);. 83.

(17) 84. Java 语言程序设计案例教程 Font f3 = new Font("TimesRoman", Font.ITALIC, 22); Font f4 = new Font("TimesRoman", Font.BOLD + Font.ITALIC, 24); // 用 f1 字体绘制字符串 g.setFont(f1); g.drawString("This is a plain font", 10, 25); // 用 f2 字体绘制字符串 g.setFont(f2); g.drawString("This is a bold font", 10, 50); // 用 f3 字体绘制字符串 g.setFont(f3); g.drawString("This is a italic font", 10, 75); // 用 f4 字体绘制字符串 g.setFont(f4); g.drawString("This is a bold and italic font", 10, 100); } }. 4.4.3 画笔颜色 1. 颜色常识 任何颜色都由三原色组成(RGB),Java 中支持 24 位彩色,即红、绿、蓝色分量取值介 于 0~255 之间。下面先了解一个 Java 中的 Color 类。 Color 的构造函数: public Color(int r,int g,int b);. 使用举例:如果想构造一个灰色对象,则用下面的句子: Color gray=new Color(205,205,205);. Color 中的常量: public final static Color black=new Color(0,0,0); public final static Color blue=new Color(0,0,255); ……. 2. 设置画笔颜色语法 g.setColor(color); //color 是一个 Color 对象. 每修改一次颜色,它影响的就是下面所有的绘图语句,一直影响到再次碰到 setColor 函数 才以新的颜色代替。 3. 使用 ColorChooser 组件选择颜色 Java 中有一个已经定义好的选色器,通过简单的语法就可以将该窗口调出来,从其中选 择自己喜欢的颜色。下面的这个例子就是通过颜色选取器选取颜色,并将选择到的颜色作为窗 体的背景色。ColorChooser 组件的 showDialog()方法让用户从弹出的窗口中选择一个颜色,并 传给 Color 对象。其调用语法如下: color=JColorChooser.showDialog(this,"选色", color);. 第一个参数指定调用选色器的父窗体,第二个参数指定选色器窗口标题,最后一个为接 收颜色的颜色对象。 【例 4.12】用不同颜色绘制字符串。 //DrawColor.java import java.awt.*; import java.applet.*; public class DrawColor extends Applet {.

(18) 第 4 章 图形用户界面设计 public void paint(Graphics g) { // 采用系统默认的颜色(黑色) g.drawString("This is a default color", 10, 10); // 设置红色的前景色 g.setColor(Color.red); g.drawString("This is red color", 10, 40); // 设置绿色的前景色 g.setColor(Color.green); g.drawString("This is green color", 10, 80); g.drawRect(10, 100, 50, 80); } }. 4.5. 框架与面板. 4.5.1 框架(Frame) 框架是 GUI 应用程序的主窗口,是顶层容器。所谓容器是指能够容纳其他组件的特殊组 件,由于容器也是组件的一种,因此容器中也能容纳容器。框架可重定义尺寸大小,能最大化、 最小化,带边框,可以指定标题、图标和窗口光标。框架可包含菜单,使用对话框。在 Java 中每个 GUI 程序至少要有一个框架,Applet 有时也会使用框架。 在 Java 中,UI 的组成如图 4.8 所示。. 图 4.8 UI 的组成结构. Frame 的构造方法如下: (1)Frame():构造一个框架,标题为空,使用缺省布局管理器。 (2)Frame(GraphicsConfiguration gc):构造一个使用特定图形配置的框架。 (3)Frame(String title):构造一个带标题的框架。 (4)Frame(String title, GraphicsConfiguration gc):构造一个使用特定图形配置带标题的 框架。 当用 Frame 类的构造函数创建一个框架实例时,被创建的对象初始是不可见的,需调用 相关的方法进行显示。. 85.

(19) 86. Java 语言程序设计案例教程. 【例 4.13】创建一个框架对象 frame,设置其大小并显示。 //FrameDemo.java import java.awt.*; import java.awt.event.*; public class FrameDemo { public static void main(String[] args) { // 创建一个 Frame 对象,作为顶层容器对象 Frame frame = new Frame("Application"); // 设置窗口为固定大小 frame.setResizable(false); frame.setSize(300, 150); // 创建监听器对象,以关闭程序 frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e){ System.exit(0); } }); // 显示窗体 frame.setVisible(true); } }. 执行这段程序,显示的主窗口如图 4.9 所示。. 图 4.9 例 4.13 程序运行结果. 4.5.2 面板(Panel) 面板不能单独存在,它必须包含在其他容器内,而且它是没有外观的,但它却是十分重 要的容器,用来实现各种基本组件的组合,面板中也能放面板。Panel 的构造方法如下: (1)Panel():构造一个空白面板,使用缺省的布局管理器 FlowLayout。 (2)Panel(LayoutManager layout):构造一个指定布局管理器的面板。 构造完面板后,使用面板对象的 add()方法添加组件即可。 【例 4.14】创建一个面板对象 panel1,将它放到主框架对象 frame 中。 //FrameDemo.java import java.awt.*; import java.awt.event.*; public class FrameDemo { public static void main(String[] args) { // 创建一个 Frame 对象,作为顶层容器对象 Frame frame = new Frame("Application"); // 创建一个面板对象,将它放到主框架.

(20) 第 4 章 图形用户界面设计 Panel panel1 = new Panel(); frame.add(panel1); // 设置窗口为固定大小 frame.setResizable(false); frame.setSize(300, 150); // 创建监听器对象,以关闭程序 frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e){ System.exit(0); } }); // 显示窗体 frame.setVisible(true); } }. 4.6. 按钮、标签、文本框与文本区域. 这里的基本组件是指除了容器类及其子类以外,Component 类派生的其他一些具体类,下 面介绍这些组件,并使用 Applet 来演示如何生成和使用它们。 4.6.1 按钮(Button) 按钮是一个组件,它用于在被按下或被按下再释放时启动相应的操作,按钮可以在声明 的时候用字符来标识(label),字符串在显示上总是位于按钮对象的中央,也可以没有字符串 标识。 按钮的构造方法如下: (1)Button():创建一个没有字符串标识的按钮。 (2)Button(String name):创建一个标识为 name 的按钮。 Button 类提供的几个主要方法如下: (1)public void setLabel(String newname):设置新标识为 newname。 (2)public String getLabel():获得按钮的标识。 (3)publc void setEnable(boolean b):设置按钮是否能用,true 为可用,false 为禁用,这 是 Component 类的方法,Button 类继承使用。 【例 4.15】创建两个按钮对象 button1 和 button2,将其添加到当前容器中。 //ButtonSample.java import java.awt.*; import java.applet.*; public class ButtonSample extends Applet { public void init() { Button button1=new Button(); Button button2=new Button("second"); button1.setLabel("first"); button1.setEnabled(true); button2.setEnabled(false); this.add(button1);. 87.

(21) 88. Java 语言程序设计案例教程 this.add(button2); } }. 程序运行结果如图 4.10 所示。. 图 4.10 例 4.15 程序运行结果. 4.6.2 标签(Label) 标签(Label)是最简单的 AWT 组件,用于在容器中加入文本字符串,在界面上不能对它 进行操作,标签的位置可以指定为左、右或中间三种对齐方式。 标签类的构造方法如下: (1)Label():声明一个空白标签。 (2)Label(String name):声明一个显示为 name 的标签。 (3)Label(String name,int alignment):声明一个显示为 name 的标签,对齐方式为 alignment, 取值为 Label.LEFT、Label.RIGHT、Label.CENTER 这三个常量中的一个。 Label 类提供的主要方法如下: (1)public void setText(String text):设置标签内容。 (2)public void setAlignment(int alignment):设置标签位置。 下面是标签应用的小例子。 【例 4.16】创建三个标签对象 label1、label2 和 label3,将其添加到当前容器中。 //LabelSample.java import java.awt.*; import java.applet.*; public class LabelSample extends Applet { public void init() { Label label1 = new Label(); Label label2 = new Label("second"); Label label3 = new Label("third",Label.RIGHT); label1.setText("first"); label1.setAlignment(Label.LEFT); label2.setAlignment(Label.CENTER); add(label1); add(label2); add(label3); } }.

(22) 第 4 章 图形用户界面设计. 程序运行结果如图 4.11 所示。. 图 4.11 例 4.16 程序运行结果. 注意. 由于这里设置了对齐方式,所以三个标签的添加顺序无所谓,也就是说,不管 先添加哪个标签,后添加哪个,运行结果都一样。. 4.6.3 文本框(TextField)与文本区域(TextArea) TextField 是文本框,TextArea 是文本区域,它们都是 TextComponent 类的子类,TextArea 自动支持滚动条。 TextField 的构造方法如下: (1)TextField():声明一个空文本框。 (2)TextField(String text):声明一个文本框,内容为 text。 (3)TextField(int length):声明长度为 length 的文本框。 (4)TextField(String text,int length):声明一个长度为 length,内容为 text 的文本框。 TextField 类提供的主要方法如下: (1)public void setText(String text):设置文本区的内容。 (2)public void setEchoChar(char c):设置显示的响应字符。 (3)public void setEditable(boolean):设置是否能编辑。 (4)public void setColumns(int columns):设置长度。 (5)public String getText():获得文本区所有的内容。 (6)public void select(int start,int end):选择字符位置从 start 到 end 的文本内容。 (7)public void selectAll():选择所有的文本内容。 (8)public void getSelectedText():获得选择的文本内容。 TextArea 的构造方法如下: (1)TextArea():声明一个空文本区。 (2)TextArea(int rows,int columns):声明一个行数为 rows,列数为 columns 的文本区。 (3)TextArea(String text):声明一个内容为 text 的文本区。 (4)TextArea(String text,int rows,int columns):声明一个内容为 text,行数为 rows,列数 为 columns 的文本区。 (5)TextArea(String text,int rows,int columns, int scrollbars):声明一个内容为 text,行数 为 rows,列数为 columns 的文本区。滚动条方式为指定方式,有以下几种:. 89.

(23) 90. Java 语言程序设计案例教程. SCROLLBARS_BOTH:水平和垂直都有滚动条。 SCROLLBARS_HORIZONTAL_ONLY:只有水平滚动条。 SCROLLBARS_VERTICAL_ONLY:只有垂直滚动条。 SCROLLBARS_NONE:没有滚动条。 TextArea 类提供的主要方法如下: (1)public void setText(String text):设置文本区的内容。 (2)public void setEditable(boolean editmode):设置是否能编辑。 (3)public void setColunms(int columns):设置列数。 (4)public void setRows(int rows):设置行数。 (5)public void appendText(String text):添加字符串。 (6)public void getText():获得文本区所有的内容。 (7)public void select(int start,int end):选择字符位置从 start 到 end 的文本区。 (8)public void selectAll():选择所有的文本内容。 (9)public void getSelectedText():获得选择的文本内容。 【例 4.17】创建两个标签对象、两个文本框对象和一个文本域对象,将它们添加到当前 容器中。 //TextSample.java import java.awt.*; import java.applet.*; public class TextSample extends Applet { public void init() { Label notice1=new Label("please fill in the city you live:"); TextField city=new TextField(10); Label notice2=new Label("please fill in the city your occupation:"); TextField occupation=new TextField(10); TextArea comment=new TextArea ("please give some comment here:",5,30); add(notice1); add(city); add(notice2); add(occupation); add(comment); } }. 程序运行结果如图 4.12 所示。. 图 4.12 例 4.17 程序运行结果.

(24) 第 4 章 图形用户界面设计. 4.7. 事件处理机制. 前面简要介绍了 AWT 提供的 GUI 组件和容器,但是,有了 GUI 组件还是无法构造一个 应用系统的用户界面,因为这样构造出的图形用户界面是无法与用户交互的,一个完整的用户 界面系统还必须具备事件处理能力。 那什么是事件呢?事件可以简单地认为是发生在应用程序上的用户的一个操作,当用户 和应用程序进行交互时,就需要用到事件。从 JDK 1.0 到 JDK 1.1,AWT 的事件处理机制有了 很大的变化,从 JDK 1.1 开始,AWT 采用了一种新的事件处理模型——代理事件模型。较 JDK 1.0 中的事件处理模型而言,新的事件处理模型不仅更为灵活,而且完全支持 JavaBeans。 但是,这里仍会先介绍 JDK 1.1 以前的事件处理机制,不仅仅因为这是后面的事件处理模型的 基础,而且仍有很多源码是用 JDK 1.1 以前的版本写的。 Java 中的事件主要有组件类事件共 6 大类,分别是: (1)ComponentEvent (2)ContainerEvent (3)WindowEvent (4)FocusEvent (5)PaintEvent (6)MouseEvent 它们均是当组件的状态发生变化时产生的动作类事件,Java 中的事件类都包含在 JDK 的 java.awt.event 包中。 4.7.1 Java 中的事件体系结构 Java 中的事件体系结构如图 4.13 所示。. 图 4.13 Java 中的事件体系结构图. AWT 的每个事件都包含若干个域,从事件域中可以获知这个事件的详细内容。常见事件 域如下: 1.id 事件类型,AWT 中定义了下述事件类型:. 91.

(25) 92. Java 语言程序设计案例教程. ACTION_EVENT:用户执行的某种动作。 GOT_FOCUS:获得焦点。 KEY_ACTION:按下功能键。 KEY_ACTION_RELEASE:释放功能键。 KEY_PRESS:按下标准键。 KEY_RELEASE:释放标准键。 LIST_DESELECT:不选列表的某项。 LIST_SELECT:选中列表中的某项。 LOAD_FILE:载入文件。 LOSE_FOCUS:失去焦点。 MOUSE_DOWN:按下鼠标键。 MOUSE_DRAG:拖动鼠标,modifiers 域的 Alt_MASK 给出了鼠标是否按下。 MOUSE_ENTER:鼠标进入组件。 MOUSE_EXIT:鼠标离开组件。 MOUSE _MOVE:鼠标移动,此时没有按下鼠标键。 MOUSE_UP:释放鼠标。 SAVE_FILE:保存文件。 SCROLL_ABSOLUTE:滚动条拖到某个位置。 SCROLL_LINE_DOWN:滚动条向下移一行。 SCROLL_LINE_UP:滚动条向上移一行。 SCROLL_PAGE_DOWN:滚动条向下移一页。 SCROLL_PAGE_UP:滚动条向上移一页。 WINDOW_DEICONIFY:窗口非图标化。 WINDOW_DESTROY:窗口销毁。 WINDOW_EXPOSE:窗口展开。 WINDOW_ICONIFY:窗口图标化。 WINDOW_MOVED:窗口移动。 2.target 事件的作用对象,即该事件是在哪个组件上发生的。 3.when 事件发生时间。 4.x.y 事件发生的位置。 5.key 键盘事件发生时键入的键值。 6.modifiers 事件发生时的功能键值,指 Alt、Ctrl、Shift 键的状态。 (1)Alt_MASK:按下了 Alt 键。 (2)Ctrl_MASK:按下了 Ctrl 键。 (3)Meta_MASK:在 UNIX 中按下了 Alt 键。.

(26) 第 4 章 图形用户界面设计. (4)Shift_MASK:按下了 Shift 键。 7.arg 事件的其他参数,根据不同的事件有所不同。 每个事件类都提供了相应的方法以便获得该事件的各种参数和状态。例如:ActionEvent 类提供下述成员方法: (1)public String getActionCommand():获得该事件相关的命令字符串,例如按钮的标识 字符串。 (2)public int getModifiers():获得该事件发生时按下的功能键。 (3)public String paramString():获得表示该事件的参数字符串。 用户编程定义每个特定事件发生时程序应做出何种响应,这些响应代码会在对应的事件 发生时由系统自动调用。在 JDK 1.0 和以前的版本中, 任何接受和处理事件的类都是 Component 类的子类,在图形用户界面中,容器中包含了组件或其他的容器,事件可能发生在某个组件中, 也可能发生在某个作为容器的窗口中。 当一个组件获得一个事件对象时,可忽略它,不做任何处理,这时返回 false,事件会继续 往上层传递,也可对该事件进行处理,处理时调用事件对象提供的方法获得参数进行处理,处 理完后,组件可以终止事件向上层传递。若事件处理结果返回 true,则表明终止事件向上传递。 4.7.2 Component 类 Component 类中定义了一系列事件处理方法,这些方法的返回值均为 boolean 类型,用以 指明事件是否向上传递。 1.动作处理方法 用来捕捉处理在特定部件中产生的事件。当用户作用于某些组件(如按钮、选择框、菜 单项、滚动条等)时,产生的事件称为动作(action),AWT 把这类事件交由 action()方法处理。 public boolean action(Event evt, Object arg). evt 参数给出当前事件实例,其中包含了时间的详细信息。arg 参数则是动作所作用的组 件,值与 evt.arg 相同。 2.键盘事件处理方法 (1)public boolean keyDown(Event evt, int key ); (2)public boolean keyUp(Event evt, int key); 其中 key 用来指明按下或释放的键的键值,与 evt.key 值相同。 3.鼠标事件处理方法 (1)按下鼠标键:public boolean mouseDown(Event evt,int x,int y) (2)按下鼠标键拖动鼠标:public boolean mouseDrag(Event evt,int x,int y) (3)鼠标进入 Applet:public boolean mouseEnter(Event evt,int x,int y) (4)鼠标离开 Applet:public boolean mouseExit(Event evt,int x,int y) (5)移动鼠标:public boolean mouseMove(Event evt,int x,int y) (6)鼠标按钮被释放:public boolean mouseUp(Event evt,int x,int y) 传递给事件处理方法的有 3 个参数,即 evt、x 和 y。Event 是一个标识事件全部信息的类, (x,y)是发生鼠标事件的坐标位置。与 evt.x 和 evt.y 相同。. 93.

(27) 94. Java 语言程序设计案例教程. 4.通用事件处理方法 public boolean handleEvent(Event evt). 在类中重写的 action()、mouseUp()、keyUp()等方法实际上是被 handleEvent()方法简单地 调用,这个方法是组件的事件处理开关,鼠标、按键、动作等各种事件最先到 handleEvent() 方法中,被分流到各种简单的处理方法,如 mouseUp()。 如果对一个组件要重写其 handleEvent()方法,为了使所有基本事件(鼠标、键盘或动作事 件)都有机会被进行缺省处理,通常应在处理方法结束处调用父类的 handleEvent()方法。 下面的例子演示了如何接受鼠标事件 mouseDown 和键盘事件 keyDown。 【例 4.18】鼠标事件 mouseDown 和键盘事件 keyDown 应用示例。 //KeyEvent.java import java.applet.*; import java.awt.*; public class KeyEvent extends Applet { private int posx,posy; //当前要写的字符的位置 private char[] manykeys; //记录键入字符的数组 private int keynumber; //记录键入字符的数目 public KeyEvent(){ } public void init() { resize(320,240); posx=10; posy=10; manykeys=new char[100]; keynumber=0; } public void desroy() { } public void paint(Graphics g){ g.drawChars(manykeys,0,keynumber,posx,posy); } public void start() { } public void stop() { } public boolean mouseDown(Event evt,int x,int y) { //如果按下了鼠标,就在鼠标所单击处重新开始打字 //记下鼠标的位置 posx=x; posy=y; //清除字符数组 keynumber=0; return true; } public boolean mouseUp(Event evt,int x,int y) { return true; } //当按键是可显示字符时加入该字符并重绘窗口 public boolean keyDown(Event evt,int nKey) {.

(28) 第 4 章 图形用户界面设计 if(keynumber<100){ manykeys[keynumber]=(char)nKey; keynumber++; } repaint(); return true; } }. 4.7.3 代理事件模型 JDK 1.1 之后的代理事件模型中有 3 个角色:事件源、事件和事件监听器。事件处理三者 关系如图 4.14 所示。. 图 4.14 代理事件模型. 1.事件源 事件源是产生或发出事件的对象。例如,当单击了图形用户界面上的一个按钮后,按钮 就会产生一个鼠标按下的事件。此时,按钮就是事件源。前面提到,在 JDK 1.0 和以前的版本 中,任何接受和处理事件的类都是 Component 类的子类,但在 JDK 1.1 以后就不是这样了,任 何类都能接受和处理事件,接受之后,事件是由事件监听器来管理的。 2.事件 AWT 中定义了各种事件类,如鼠标事件(MouseEvent)和窗口事件(WindowEvent)等。 3.事件监听器 在 AWT 中,事件监听器是 java.awt.event 包中的一类接口,其中定义了当被监听的事件发 生时,需要调用的方法。事件监听器用于监听某类事件的发生,它通过调用事件源 add****** 方法(******代表某类事件监听器),来登记所需监听的事件。当该事件源发出此类事件时, 事件监听器就会得到通知。 例如 KeyEvent 相对应的接口 KeyListener: public interface KeyListener extends EventListener { public void keyPressed(KeyEvent ev); public void keyReleased(KeyEvent ev); public void keyTyped(KeyEvent ev); }. AWT 的组件类中提供注册和注销监听器的方法。 注册监听器: public void add<ListenerType>(<ListenerType>listener);. 95.

(29) 96. Java 语言程序设计案例教程. 如: button.addMouseListener(this);. 注销监听器: public void remove<ListenerType>(<ListenerType>listener);. 如: button.removeMouseListener(this);. 下面是一些常用的事件监听器。 (1)ActionListener:Button、List、MenuItem、TextField 接收 Action_Event 事件。 (2)ItemListener:Choice、CheckBox 接收 Action_Event 事件,接收所有的 List_事件。 (3)FocusListener:接收 Got_Focus 和 Lost_Focus 事件。 (4)KeyListener:接收所有的 Key_事件。 (5)MouseMotionListener:接收 Mouse_Drag 和 Mouse_Move 事件。 (6)MouseListener:接收除了 Mouse_Drag 和 Mouse_Move 以外的所有 Mouse_事件。 (7)AdjustmentListener:接收所有的 Scroll_事件。 (8)WindowListener:接收所有的 Window_事件,除了 Window_Moved 事件。 (9)ComponentListener:接收 Window_Moved 事件。 有了以上的接口,就可以通过如下 3 个步骤来使用它们接收和管理事件。 (1)为类声明需要的事件监听器接口 和其他的接口声明方法一样。 例如: public class AppletSample extends Applet implements ActionListener. 如果该类中需要一个以上的事件监听器,则可以根据需要声明多个。 (2)为组件登记接口 在代码中,当生成一个组件作为事件源后,就需要为这个组件登记该类已经声明过的相 应的事件监听器,然后再加入该组件,所有的组件都有这样的登记方法,方法名的格式为: add******,******是事件监听器的名字。 例如: Button button1=new Button("OK"); button1.addActionListener(this); add(button1);. 这里 addActionListener 的参数为 this,表明当组件接收到 Action_Event 事件后,该类实现 的事件监视器接口就会自动处理这个事件。 (3)最后在类中实现接口声明的处理方法 比如 ActionListener 声明的事件处理方法为 actionPerformed(),在该类中就要实现这个 方法: public void actionPerformed(ActionEvent event) { //填写所需代码 }. 4.8 我们先看一下图 4.15。. 布局设计.

(30) 第 4 章 图形用户界面设计. 图 4.15 常见的五种布局管理器设计方案. 在该图中,按钮的个数及功能相同,但在界面显示上有很大的差异,这就是布局管理器 在起作用,布局管理器具有如下功能特点: (1)布局管理器决定容器中组件的尺寸和位置。 (2)每个容器都有一个缺省的布局管理器。 (3)组件可以提供大小和排列的建议,但最终大小和位置由布局管理器决定。 (4)所有的 Panel(面板)对象在缺省状态下都使用 FlowLayout(流式布局)。 (5)内容窗格缺省使用 BorderLayout(边界布局),特点是菜单栏、工具栏的高度固定, 并且可以在界面上随意拖动。 AWT 的标准布局管理器有以下五种: (1)FlowLayout:该布局管理器将组件从左到右或从上到下放置,是 Panel 和 Applet 的 默认布局管理器。 (2)BorderLayout:该布局管理器将组件分为东、西、南、北、中五个区域,是 Window、 Dialog 和 Frame 容器的默认布局管理器。 (3)CardLayout:该布局管理器将加入到容器的组件作为卡片,把每个组件放置在一个 单独的卡片上,后面的卡片将覆盖前面的卡片,每次只能看到一张卡片。 (4)GridLayout:该布局管理器将容器分为相同尺寸的网格,将组件依次放入网格中。 (5)GridBagLayout:该布局管理器将容器分为相同尺寸的网格,但组件不只是占一个网 格,一个组件可以占多个网格位置。 4.8.1 FlowLayout 布局管理器 FlowLayout 型布局管理器对容器中组件进行布局的方式是将组件逐个地安放在容器中的 一行上,一行放满后就另起一个新行。 FlowLayout 有三种构造方法: (1)public FlowLayout() (2)public FlowLayout(int align) (3)public FlowLayout(int align, int hgap, int vgap) 在默认情况下,FlowLayout 将组件居中放置在容器的某一行上,FlowLayout 的构造方法 中提供了一个对齐方式的可选项 align,align 可取值有三个:FlowLayout.LEFT(左对齐)、. 97.

(31) 98. Java 语言程序设计案例教程. FlowLayout.RIGHT(右对齐)、FlowLayout.CENTER(居中)。 【例 4.19】将三个按钮 button1、button2 和 button3 按 FlowLayout 布局方案放入框架 f 中。 //LayoutFlow.java import java.awt.*; import java.awt.event.*; class LayoutFlow { private Frame f; private Button button1, button2, button3; public static void main(String args[]) { LayoutFlow layoutFlow = new LayoutFlow(); layoutFlow.go(); } public void go() { f = new Frame("Flow Layout"); f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); f.setLayout(new FlowLayout()); button1 = new Button("Ok"); button2 = new Button("Open"); button3 = new Button("Close"); f.add(button1); f.add(button2); f.add(button3); f.setSize(100, 100); f.setVisible(true); } }. 程序运行结果如图 4.16 所示。. 图 4.16 例 4.19 程序运行结果. 4.8.2 BorderLayout 布局管理器 BorderLayout 是 Dialog 类和 Frame 类的默认布局管理器,它提供了一种较为复杂的组件 布局管理方案,每个被 BorderLayout 管理的容器均被划分成五个区域:东(East)、南(South)、 西(West)、北(North)、中(Center)。North 在容器的上部,East 在容器的右部,其他依此 类推。Center 当然就是 East、South、West 和 North 所围绕的中部。 BorderLayout 布局管理器有两种构造方法: (1)BorderLayout()构造一个各部分间距为 0 的 BorderLayout 实例。 (2)BorderLayout(int, int)构造一个各部分具有指定间距的 BorderLayout 实例。 在 BorderLayout 布局管理器的管理下,组件必须通过 add()方法加入到容器的五个命名区 域之一。 典型的边界型界面如图 4.17 所示。 aPanel.add(new Button("北区按钮"), BorderLayout.NORTH); aPanel.add(new Button("南区按钮"), BorderLayout.SOUTH); aPanel.add(new Button("西区按钮"), BorderLayout.WEST);.

(32) 第 4 章 图形用户界面设计 aPanel.add(new Button("东区按钮"), BorderLayout.EAST);. 边界型布局的每个区中只能放一个组件,如果在同一个区内放入第二个组件的话,后者 就会覆盖前者,可以使用内部容器在 BorderLayout 的一个区域内间接放入多个组件。 如果某个区域没有使用,那么它的大小将变为零,此时 Center 区域将会扩展并占据这个 未用区域的位置,如图 4.18 所示。. 图 4.17 典型的边界型布局界面. 图 4.18 缺少某个区域的边界型布局界面. 实际上,常用的是上下排列,或者左右排列两个组件的情况。图 4.19 显示上下排列的边 界型布局和左右排列的边界型布局在调整高度和宽度时的表现。. 图 4.19 上下排列的边界型布局和左右排列的边界型布局在调整高度和宽度时的布局界面. 【例 4.20】将五个按钮 be、bw、bn、bs 和 bc 按 BorderLayout 布局方案放入框架 f 中。 ///LayoutBorder.java import java.awt.*; import java.awt.event.*; class LayoutBorder { private Frame f; private Button be, bw, bn, bs, bc; public static void main(String args[]) { LayoutBorder layoutBorder = new LayoutBorder(); layoutBorder.go(); } void go() { f = new Frame("Border Layout"); // 创建监听器对象,以关闭程序 f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); be = new Button("东区"); bs = new Button("南区"); bw = new Button("西区"); bn = new Button("北区");. 99.

(33) 100. Java 语言程序设计案例教程 bc = new Button("中间区域"); //设置布局管理器为 BorderLayout f.setLayout(new BorderLayout(20, 50)); f.add(be, BorderLayout.EAST); f.add(bw, BorderLayout.WEST); f.add(bs, BorderLayout.SOUTH); f.add(bn, BorderLayout.NORTH); f.add(bc, BorderLayout.CENTER); TextField txtField = new TextField(20); f.add(txtField); f.setSize(350, 200); f.setVisible(true); } }. 程序运行结果如图 4.20 所示。. 图 4.20 例 4.20 程序运行结果. 4.8.3 GridLayout 布局管理器 GridLayout 是一种网格式的布局管理器,它将容器空间划分成若干行乘若干列的网格,组 件依次放入其中,每个组件占据一格。 GridLayout 有三种构造方法: (1)public GridLayout() (2)public GridLayout(int rows, int cols) (3)public GridLayout(int rows, int cols, int hgap, int vgap) 第一种不带参数的构造方法创建一个只有一行的网格,网格的列数根据实际需要而定。 参数:rows 和 cols 分别指定网格的行数和列数,hgap 和 vgap 分别表示网格间的水平间距 和垂直间距。 如:new GridLayout(3,2),可以创建一个三行乘两列的布局管理器。 rows 和 cols 中的一个值可以为 0,但是两个值不能都是 0。 如果 rows 为 0,那么网格的行数将根据实际需要而定;如果 cols 为 0,那么网格的列数 将根据实际需要而定。 【例 4.21】将六个按钮 b1、b2、b3、b4、b5 和 b6 按 GridLayout 布局方案放入框架 f 中。 //LayoutDemo.java import java.awt.*; import java.awt.event.*; class LayoutGrid { private Frame f; private Button b1,b2,b3,b4,b5,b6; public static void main(String args[]) { LayoutGrid layoutGrid = new LayoutGrid(); layoutGrid.show(); } void show() { f = new Frame("Layout example"); //f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); // 创建监听器对象,以关闭程序 f.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) {.

(34) 第 4 章 图形用户界面设计 101 System.exit(0); } }); //将布局管理器设置为网格类型 f.setLayout(new GridLayout(0,2,10,20)); f.setSize(300,200); b1 = new Button("b1"); b2 = new Button("b2"); b3 = new Button("b3"); b4 = new Button("b4"); b5 = new Button("b5"); b6 = new Button("b6"); f.add(b1); f.add(b2); f.add(b3); f.add(b4); f.add(b5); f.add(b6); TextField txtField = new TextField(30); f.add(txtField); f.pack(); f.setVisible(true); } }. 运行结果如图 4.21 所示。. 图 4.21 例 4.21 程序运行结果. 4.8.4 CardLayout 布局管理器 CardLayout 是一种卡片式的布局管理器,卡片式布局是一种非常特殊的布局方式,它所 管理的不是组件,而是面板。采用卡片式布局的面板,会同时拥有若干个与它大小相同的子面 板,但在界面上每次只显示其中一个子面板。如同摞在一起的卡片一样,每次只能显示最顶上 的一张。 【例 4.22】卡片式布局管理器 CardLayout 应用示例。 //LayoutCard.java import java.awt.*; import java.awt.event.*; public class LayoutCard { CardLayout cardlay; Panel panel;.

(35) 102. Java 语言程序设计案例教程 Button b1; int cardno = 0; final int NCARDS = 4; String labels[] = new String[NCARDS]; Frame frame; public static void main(String[] args) { LayoutCard layoutCard = new LayoutCard(); layoutCard.go(); } void go() { frame = new Frame("Border Layout"); //创建监听器对象,以关闭程序 frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); panel = new Panel(); cardlay = new CardLayout(); b1 = new Button("Next"); b1.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent evt){ if (++cardno >= NCARDS) cardno = 0; cardlay.show(panel, labels[cardno]); } }); labels[0] = "Card One"; labels[1] = "Card Two"; labels[2] = "Card Three"; labels[3] = "Card Four"; panel.setLayout(cardlay); for (int i = 0; i < NCARDS; i++) panel.add(labels[i], new Label(labels[i])); cardlay.show(panel, labels[0]); frame.setLayout(new BorderLayout()); frame.add("Center",panel); frame.add("South", b1); frame.setSize(200,100); frame.setVisible(true); } }. 程序运行结果如图 4.22 所示。. 图 4.22 例 4.22 程序运行结果.

(36) 第 4 章 图形用户界面设计 103. 4.8.5 GridBagLayout 布局管理器 GridBagLayout 布局是最灵活、最复杂的布局之一,它比较接近表格型布局,但远比后者 灵活,可以定制每一格的大小、间隙等。GridBagLayout 的掌握有一定难度,下面首先通过一 个例子来直接演示这种布局的显示效果,再逐一分析这种效果是怎么做到的。 假设程序运行效果如图 4.23 所示。. 图 4.23 例 4.23 程序运行结果. 【例 4.23】表格包式布局管理器 GridBagLayout 应用示例。 //LayoutGridBag.java import java.awt.*; import java.awt.event.*; public class LayoutGridBag { public static void main(String[] args) { Frame frame = new Frame("表格包式布局"); // 创建监听器对象,以关闭程序 frame.addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); Panel panel = new Panel(); panel.setLayout(new GridBagLayout()); Button button; GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.HORIZONTAL; button = new Button("新建文件"); c.weightx = 0.5; c.gridx = 0; c.gridy = 0; panel.add(button, c); button = new Button("打开"); c.gridx = 1; c.gridy = 0; panel.add(button, c); button = new Button("另存为"); c.gridx = 2; c.gridy = 0; panel.add(button, c); button = new Button("关闭(仅关闭打开的文件,而非整个程序)"); c.ipady = 40;.

(37) 104. Java 语言程序设计案例教程 c.weightx = 0.0; c.gridwidth = 3; c.gridx = 0; c.gridy = 1; panel.add(button, c); button = new Button("退出程序"); c.ipady = 0; c.weighty = 1.0; c.anchor = GridBagConstraints.PAGE_END; c.insets = new Insets(10, 0, 0, 0); c.gridx = 1; c.gridwidth = 2; c.gridy = 2; panel.add(button, c); frame.add(panel); frame.pack(); frame.setVisible(true); } }. 说明: 表格包型布局的灵活性主要体现在它可以对每个单元格、每个组件进行配置它需要的表 格包约束(GridBagConstraints)类的辅助。这个约束类的作用只有一个,就是配置每个单元格 里的组件。 下面的代码用于在表格包中加入组件: panel.setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); panel.add(component, c);. 代码的第一行设置布局管理器为表格包型,第二行代码产生一个约束对象,随后对约束 对象进行配置,最后调用 add 函数添加组件,add 函数的第二个参数为约束对象 c,组件的配 置信息就存储在约束对象 c 里,下面针对每个组件的约束对象 c 进行分析: “新建文件”按钮有 4 个约束: button = new Button("新建文件"); c.fill = GridBagConstraints.HORIZONTAL; c.gridx = 0; c.gridy = 0; c.weightx = 0.5; panel.add(button, c);. “fill”:指示当组件的显示区域大于组件尺寸时,应当怎么办,缺省值是 NONE,也就是 说组件大小不变。其值有 HORIZONTAL(宽度),表示将组件拉宽到与单元格宽度一致,但 高度不变。VERTICAL(高度),表示将组件高度提升到与单元格高度一致,但宽度不变。BOTH (同时),表示将组件的高度和宽度都拉伸到与单元格一致。本例中,这个约束是对所有组件 起作用的。 “gridx”,“gridy”:组件所在的单元格位置,例如:gridx = 0, gridy = 0,表示组件位于左 上角的单元格;gridx = 1, gridy = 2 表示组件位于第 2 列、第 3 行的单元格;建议对每个组件 都指定它所在的单元格。.

(38) 第 4 章 图形用户界面设计 105. “weightx”,“weighty”:确定当用户拉大主程序界面时,各单元格如何分配多余的空间, 这通过单元格的权重(weight)来确定,当用户拉大了窗口的宽度时,权重为 0 的单元格的宽 度不变,其他权重大于 0 的单元格按比例分配多出来的宽度。weighty 用于设置单元格高度的 权重,权重的绝对值不重要,关键是其相对比例。 第 4 个按钮引入了两个新的约束“gridwidth”和“ipady”,下面介绍这两个约束。 “gridwidth”,“gridheight”:分别表示这个组件在宽度和高度上分别占用了几个单元格。 变量的值表示单元格个数,而不是像素数。本例中,由于第 4 个按钮很长,一个单元格放不下, 因此设 gridwidth = 3,也就是横向占据 3 个单元格的位置,但纵向仍然只占据了一个单元格的 位置。 “ipadx”,“ipady”:设定组件内部的填充宽度或高度。由于填充是针对两边的,因此组件 的高度至少应为它的最小高度加上 ipady*2。本例中,为了提高第 4 个按钮的高度,同时将字 体居中,设置它的内部填充高度为 40。 第 5 个按钮又引入了两个新的约束“insets”和“anchor”,下面分别介绍。 “insets”:定义组件的外部填充,也就是说,在组件和单元格之间的空隙是多少。外部填 充值是通过一个 Insets 对象来指定的,它的构造函数的 4 个参数分别是组件顶部、左侧、底部、 右侧的填充值。 c.insets = new Insets(10,0,0,0); 本例中,指定第 5 个按钮的顶部与单元格之间有 10 个像素的空隙。 “anchor”:设定当组件小于单元格时,应该怎样放置单元格。组件有 9 种放置方式: (1)FIRST_LINE_START(左上角) (2)PAGE_START(上部的中间) (3)FIRST_LINE_END(右上角) (4)LINE_START(左侧的中间) (5)CENTER(正中间) (6)LINE_END(右侧的中间) (7)LAST_LINE_START(左下角) (8)PAGE_END(下部的中间) (9)LAST_LINE_END(右下角) 9 种放置方式的位置图如图 4.24 所示。. 图 4.24 组件的 9 种放置方式.

(39) 106. Java 语言程序设计案例教程. 在添加组件约束的时候,如果每个组件都共用一个约束,那么要注意还原设定值。例如 第 4 个按钮设定 ipady 为 40,但第 5 个按钮不需要设置内部填充,因此在定义第 5 个按钮的约 束时要将 ipady 设为 0,否则前面定义的约束会一直传给后面的组件。相反,本例中 fill 属性 就从头传到尾,为所有单元格所用。. 4.9. 菜单设计. 菜 单 是 非 常 重 要 的 GUI 组 件 。 Java 的 菜 单 组 件 是 由 多 个 类 组 成 的 , 其 中 , java.awt.MenuComponent 类是所有菜单类的父类,它的子类有:MenuBar(菜单条) 、Menu(菜 单)、MenuItem(菜单子项)、CheckboxMenuItem(复选框菜单子项)、PopupMenu(弹出菜单)。 此外,还有一个用于产生快捷键的类:MenuShortcut。 每个菜单组件都包括一个菜单条,每个菜单条又包含若干个菜单项,每个菜单项再包含 若干个菜单子项。菜单子项的作用与按钮类似,当用户单击时产生一个命令动作。 Java 中的菜单分为两大类:一类是菜单条式菜单,通常所说的菜单就是这一类;另一类 就是弹出式菜单。 创建一个菜单的步骤如下: (1)创建菜单条。菜单条组件是一个水平菜单。它只能加入到一个框架中,并成为所有菜 单树的根。在一个时刻,一个框架可以显示一个菜单条。然而,可以根据程序的状态修改菜单 条,这样,在不同的时刻就可以显示不同的菜单。一般使用 MenuBar 组件,菜单条外观如图 4.25 所示。. 图 4.25 菜单条外观. 为了将该菜单栏与 Frame 对象关联,可以调用该框架的 setMenuBar 方法。 MenuBar 组件只有一种构造方式,但是它对于构造一个菜单来说是个不可缺少的组件。 (2)创建菜单项,添加到菜单条中。 使用 Menu 组件。Menu 组件是用来存放和整合 MenuItem 的组件,这个组件也是构成一 个菜单不可或缺的组件之一。Menu 可以是单一层次的结构也可以是一个层次式的结构,要使 用何种形式的结构取决于界面设计上的需要而定。 (3)将菜单子项加入到菜单项中,菜单子项是菜单树的“叶”节点。 使用 MenuItem 组件。MenuItem 继承 AbstractButton 类,可以说 MenuItem 是一种特殊的 Button,所以 MenuItem 支持许多在 Button 中好用的功能,例如加入图标文件或是在菜单中选 择某一项 MenuItem 时就如同按下按钮的操作一样触发 ActionEvent,通过 ActionEvent 的机制 就能针对不同的 MenuItem 编写其对应的程序段。.

(40) 第 4 章 图形用户界面设计 107. (4)将建成的菜单条加入到容器中。 (5)将菜单子项注册给动作事件的监听者 ActionListener。 (6)重载监听者的方法 actionPerformed(ActionEvent e)。 【例 4.24】创建菜单示例。 //MenuDemo.java import java.applet.Applet; import java.awt.*; import java.awt.event.*; public class MenuDemo extends Frame implements ActionListener { Menu objMenuFile; Menu objMenuEdit; Label lblMsg; public void init() { setBackground(Color.white); buildMenuFile(); buildMenuEdit(); MenuBar objMenuBar = new MenuBar(); setMenuBar(objMenuBar); objMenuBar.add(objMenuFile); objMenuBar.add(objMenuEdit); lblMsg = new Label("显示的消息."); add(lblMsg); } private void buildMenuFile() { MenuItem objMenuItem; objMenuFile = new Menu("文件"); objMenuItem = new MenuItem("新建"); objMenuItem.addActionListener(this); objMenuFile.add(objMenuItem); objMenuItem = new MenuItem("打开"); objMenuItem.addActionListener(this); objMenuFile.add(objMenuItem); objMenuItem = new MenuItem("保存"); objMenuItem.addActionListener(this); objMenuFile.add(objMenuItem); objMenuItem = new MenuItem("另存为"); objMenuItem.addActionListener(this); objMenuFile.add(objMenuItem); objMenuFile.addSeparator(); // 添加水平分割线 objMenuItem = new MenuItem("退出"); objMenuItem.addActionListener(this); objMenuFile.add(objMenuItem); } private void buildMenuEdit() { MenuItem objMenuItem; objMenuEdit = new Menu("编辑"); objMenuItem = new MenuItem("撤销"); objMenuItem.addActionListener(this); objMenuEdit.add(objMenuItem); objMenuItem = new MenuItem("重做"); objMenuItem.addActionListener(this); objMenuEdit.add(objMenuItem); objMenuEdit.addSeparator(); objMenuItem = new MenuItem("剪切");.

參考文獻

相關文件

The Performance Evaluation for Horizontal, Vertical and Hybrid Schema in Database Systems.. -A Case Study of Wireless Broadband

“告诉大家一个好消息和一个坏消息。好消息是下星期不考试了! ”同学们

再以后,两个人频繁地约会,她发现他实际上是一个很好的男人,大度、细

通过 HSK(二级)的考生可以用汉语就熟悉的日常话题进行简单而直接的 交流,达到初级汉语优等水平。..

如果讲“危”的话,这个时候是现金为王,首先我们自己的现金流是足

通过 HSK(二级)的考生可以用汉语就熟悉的日常话题进行简单而直接的 交流,达到初级汉语优等水平。..

有个人出名之前,穿得很随便。朋友对他说,应该买件漂亮的大衣。他 笑着回答:

[r]