友情提示:如果本网页打开太慢或显示不完整,请尝试鼠标右键“刷新”本网页!
Java编程思想第4版[中文版](PDF格式)-第68部分
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部! 如果本书没有阅读完,想下次继续接着阅读,可使用上方 "收藏到我的浏览器" 功能 和 "加入书签" 功能!
程序片置入 Web 页,需要在那个Web 页的代码中设置一个特殊的标记(注释①),以指示网页装载和运行程
序片。这就是applet 标记,它在 Applet1 中的样子如下:
①:本书假定读者已掌握了HTML 的基本知识。这些知识不难学习,有许多书籍和网上资源都可以提供帮助。
其中,code 值指定了。class 文件的名字,程序片就驻留在那个文件中。width 和height 指定这个程序片的
初始尺寸(如前所述,以像素为单位)。还可将另一些东西放入applet 标记:用于在因特网上寻找其
他。class 文件的位置(codebase )、对齐和排列信息(align)、使程序片相互间能够通信的一个特殊标识
符(name )以及用于提供程序片能接收的信息的参数。参数采取下述形式:
可根据需要设置任意多个这样的参数。
在简单的程序片中,我们要做的唯一事情是按上述形式在 Web 页中设置一个程序片标记(applet),令其装
载和运行程序片。
13。2。1 程序片的测试
我们可在不必建立网络连接的前提下进行一次简单的测试,方法是启动我们的Web 浏览器,然后打开包含了
程序片标签的HTML 文件(Sun 公司的 JDK 同样包括一个称为“程序片观察器”的工具,它能挑出html 文件
的标记,并运行这个程序片,不必显示周围的HTML 文本——注释②)。html 文件载入后,浏览器
会发现程序片的标签,并查找由code 值指定的。class 文件。当然,它会先在 CLASSPATH (类路径)中寻找,
如果在CLASSPATH 下找不到类文件,就在 WEB 浏览器状态栏给出一个错误信息,告知不能找到。class 文件。
②;由于程序片观察器会忽略除APPLET 标记之外的任何东西,所以可将那些标记作为注释置入Java 源码:
//
这样就可直接执行“appletviewer MyApplet。java”,不必再创建小的HTML 文件来完成测试。
若想在Web 站点上试验,还会碰到另一些麻烦。首先,我们必须有一个Web 站点,这对大多数人来说都意味
着位于远程地点的一家服务提供商(ISP)。然后必须通过某种途径将HTML 文件和。class 文件从自己的站点
移至 ISP机器上正确的目录(WWW 目录)。这一般是通过采用“文件传输协议”(FTP)的程序来做成的,网
上可找到许多这样的免费程序。所以我们要做的全部事情似乎就是用 FTP 协议将文件移至 ISP 的机器,然后
用自己的浏览器连接网站和HTML 文件;假如程序片正确装载和执行,就表明大功告成。但真是这样吗?
380
…………………………………………………………Page 382……………………………………………………………
但这儿我们可能会受到愚弄。假如 Web 浏览器在服务器上找不到。class 文件,就会在你的本地机器上搜寻
CLASSPATH。所以程序片或许根本不能从服务器上正确地装载,但在你看来却是一切正常的,因为浏览器在你
的机器上找到了它需要的东西。但在其他人访问时,他们的浏览器就无法找到那些类文件。所以在测试时,
必须确定已从自己的机器删除了相关的。class文件,以确保测试结果的真实。
我自己就遇到过这样的一个问题。当时是将程序片置入一个 package (包)中。上载了HTML 文件和程序片
后,由于包名的问题,程序片的服务器路径似乎陷入了混乱。但是,我的浏览器在本地类路径(CLASSPATH)
中找到了它。这样一来,我就成了能够成功装载程序片的唯一一个人。后来我花了一些时间才发现原来是
package 语句有误。一般地,应该将package 语句置于程序片的外部。
13。2。2 一个更图形化的例子
这个程序不会太令人紧张,所以让我们试着增加一些有趣的图形组件。
//: Applet2。java
// Easy graphics
import java。awt。*;
import java。applet。*;
public class Applet2 extends Applet {
public void paint(Graphics g) {
g。drawString(〃Second applet〃; 10; 15);
g。draw3DRect(0; 0; 100; 20; true);
}
} ///:~
这个程序用一个方框将字符串包围起来。当然,所有数字都是“硬编码”的(指数字固定于程序内部),并
以像素为基础。所以在一些机器上,框会正好将字串围住;而在另一些机器上,也许根本看不见这个框,因
为不同机器安装的字体也会有所区别。
对Graphic 类而言,可在帮助文档中找到另一些有趣的内容。大多数涉及图形的活动都是很有趣的,所有我
将更多的试验留给读者自己去进行。
13。2。3 框架方法的演示
观看框架方法的实际运作是相当有趣的(这个例子只使用 init(),start()和 stop(),因为 paint()和
destroy()非常简单,很容易就能掌握)。下面的程序片将跟踪这些方法调用的次数,并用paint()将其显示
出来:
//: Applet3。java
// Shows init(); start() and stop() activities
import java。awt。*;
import java。applet。*;
public class Applet3 extends Applet {
String s;
int inits = 0;
int starts = 0;
int stops = 0;
public void init() { inits++; }
public void start() { starts++; }
public void stop() { stops++; }
public void paint(Graphics g) {
s = 〃inits: 〃 + inits +
〃; starts: 〃 + starts +
381
…………………………………………………………Page 383……………………………………………………………
〃; stops: 〃 + stops;
g。drawString(s; 10; 10);
}
} ///:~
正常情况下,当我们过载一个方法时,需检查自己是否需要调用方法的基础类版本,这是十分重要的。例
如,使用 init()时可能需要调用super。init()。然而,Applet 文档特别指出 init()、start()和 stop()在
Applet 中没有用处,所以这里不需要调用它们。
试验这个程序片时,会发现假如最小化WEB 浏览器,或者用另一个窗口将其覆盖,那么就不能再调用 stop()
和 start() (这一行为会随着不同的实现方案变化;可考虑将Web 浏览器的行为同程序片观察器的行为对照
一下)。调用唯一发生的场合是在我们转移到一个不同的 Web 页,然后返回包含了程序片的那个页时。
13。3 制作按钮
制作一个按钮非常简单:只需要调用Button 构建器,并指定想在按钮上出现的标签就行了(如果不想要标
签,亦可使用默认构建器,但那种情况极少出现)。可参照后面的程序为按钮创建一个句柄,以便以后能够
引用它。
Button 是一个组件,象它自己的小窗口一样,会在更新时得以重绘。这意味着我们不必明确描绘一个按钮或
者其他任意种类的控件;只需将它们纳入窗体,以后的描绘工作会由它们自行负责。所以为了将一个按钮置
入窗体,需要过载 init()方法,而不是过载 paint():
//: Button1。java
// Putting buttons on an applet
import java。awt。*;
import java。applet。*;
public class Button1 extends Applet {
Button
b1 = new Button(〃Button 1〃);
b2 = new Button(〃Button 2〃);
public void init() {
add(b1);
add(b2);
}
} ///:~
但这还不足以创建 Button (或其他任何控件)。必须同时调用Applet add()方法,令按钮放置在程序片的窗
体中。这看起来似乎比实际简单得多,因为对 add()的调用实际会(间接地)决定将控件放在窗体的什么地
方。对窗体布局的控件马上就要讲到。
13。4 捕获事件
大家可注意到假如编译和运行上面的程序片,按下按钮后不会发生任何事情。必须进入程序片内部,编写用
于决定要发生什么事情的代码。对于由事件驱动的程序设计,它的基本目标就是用代码捕获发生的事件,并
由代码对那些事件作出响应。事实上,GUI 的大部分内容都是围绕这种事件驱动的程序设计展开的。
经过本书前面的学习,大家应该有了面向对象程序设计的一些基础,此时可能会想到应当有一些面向对象的
方法来专门控制事件。例如,也许不得不继承每个按钮,并过载一些“按钮按下”方法(尽管这显得非常麻
烦有有限)。大家也可能认为存在一些主控“事件”类,其中为希望响应的每个事件都包含了一个方法。
在对象以前,事件控制的典型方式是 switch 语句。每个事件都对应一个独一无二的整数编号;而且在主事件
控制方法中,需要专门为那个值写一个 switch。
Java 1。0 的AWT 没有采用任何面向对象的手段。此外,它也没有使用switch 语句,没有打算依靠那些分配
给事件的数字。相反,我们必须创建 if 语句的一个嵌套系列。通过 if语句,我们需要尝试做的事情是侦测
到作为事件“目标”的对象。换言之,那是我们关心的全部内容——假如某个按钮是一个事件的目标,那么
382
…………………………………………………………Page 384……………………………………………………………
它肯定是一次鼠标点击,并要基于那个假设继续下去。但是,事件里也可能包含了其他信息。例如,假如想
调查一次鼠标点击的像素位置,以便画一条引向那个位置的线,那么 Event 对象里就会包含那个位置的信息
(也要注意Java 1。0 的组件只能产生有限种类的事件,而Java 1。1 和 Swing/JFC 组件则可产生完整的一系
列事件)。
Java 1。0 版的AWT 方法串联的条件语句中存在action()方法的调用。虽然整个 Java 1。0 版的事件模型不兼
容Java 1。1 版,但它在还不支持 Java1。1 版的机器和运行简单的程序片的系统中更广泛地使用,忠告您使用
它会变得非常的舒适,包括对下面使用的 action()程序方法而言。
action()拥有两个自变量:第一个是事件的类型,包括所有的触发调用 action()的事件的有关信息。例如鼠
标单击、普通按键按下或释放、特殊按键按下或释放、鼠标移动或者拖动、事件组件得到或丢失焦点,等
等。第二个自变量通常是我们忽略的事件目标。第二个自变量封装在事件目标中,所以它像一个自变量一样
的冗长。
需调用action() 时情况非常有限:将控件置入窗体时,一些类型的控件(按钮、复选框、下拉列表单、菜
单)会发生一种“标准行动”,从而随相应的 Event 对象发起对 action()的调用。比如对按钮来说,一旦按
钮被按下,而且没有再多按一次,就会调用它的action()方法。这种行为通常正是我们所希望的,因为这正
是我们对一个按钮正常观感。但正如本章后面要讲到的那样,还可通过 handleEvent()方法来处理其他许多
类型的事件。
前面的例程可进行一些扩展,以便象下面这样控制按钮的点击:
//: Button2。java
// Capturing button presses
import java。awt。*;
import java。applet。*;
public class Button2 extends Applet {
Button
b1 = new Button(〃Button 1〃);
b2 = new Button(〃Button 2〃);
public void init() {
add(b1);
add(b2);
}
public boolean action(Event evt; Object arg) {
if(evt。target。equals(b1))
getAppletContext()。showStatus(〃Button 1〃);
else if(evt。target。equals(b2))
getAppletContext()。showStatus(〃Button 2〃);
// Let the base class handle it:
else
return super。action(evt; arg);
return true; // We've handled it here
}
} ///:~
为了解目标是什么,需要向Event 对象询问它的target (目标)成员是什么,然后用equals()方法检查它是
否与自己感兴趣的目标对象句柄相符。为所有感兴趣的对象写好句柄后,必须在末尾的else 语句中调用
super。action(evt; arg)方法。我们在第7 章已经说过(有关多形性的那一章),此时调用的是我们过载过
的方法,而非它的基础类版本。然而,基础类版本也针对我们不感兴趣的所有情况提供了相应的控制代码。
除非明确进行,否则它们是不会得到调用的。返回值指出我们是否已经处理了它,所以假如确实与一个事件
相符,就应返回true;否则就返回由基础类 event()返回的东西。
对这个例子来说,最简单的行动就是打印出到底是什么按钮被按下。一些系统允许你弹出一个小消息窗口,
但Java 程序片却防碍窗口的弹出。不过我们可以用调用 Applet 方法的 getAppletContext()来访问浏览器,
然后用 showStatus()在浏览器窗口底部的状态栏上显示一条信息(注释③)。还可用同样的方法打印出对事
383
…………………………………………………………Page 385……………………………………………………………
件的一段完整说明文字,方法是调用getAppletConext()。showStatus(evt + 〃〃)。空字串会强制编译器将
evt 转换成一个字符串。这些报告对于测试和调试特别有用,因为浏览器可能会覆盖我们的消息。
③:ShowStatus()也属于 Applet 的一个方法,所以可直接调用它,不必调用getAppletContext() 。
尽管看起来似乎很奇怪,但我们确实也能通过 event()中的第二个参数将一个事件与按钮上的文字相配。采
用这种方法,上面的例子就变成了:
//: Button3。java
// Matching events on button text
import java。awt。*;
import java。applet。*;
public class Button3 extends Applet {
Button
b1 = new Button(〃Button 1〃);
b2 = new Button(〃Button 2〃);
public void init() {
add(b1);
add(b2);
}
public boolean action (Event evt; Object arg) {
if(arg。equals(〃Button 1〃))
getAppletContext()。showStatus(〃Button 1〃);
else if(arg。equals(〃Button 2〃))
getAppletContext()。showStatus(〃Button 2〃);
// Let the base class handle it:
else
return super。action(evt; arg);
return true; // We've handled it here
}
} ///:~
很难确切知道equals()方法在这儿要做什么。这种方法有一个很大的问题,就是开始使用这个新技术的 Java
程序员至少需要花费一个受挫折的时期来在比较按钮上的文字时发现他们要么大写了要么写错了(我就有这
种经验)。同样,如果我们改变了按钮上的文字,程序代码将不再工作(但我们不会得到任何编译时和运行
时的信息)。所以如果可能,我们就得避免使用这种方法。
13。5 文本字段
“文本字段”是允许用户输入和编辑文字的一种线性区域。文本字段从文本组件那里继承了让我们选择文
字、让我们像得到字符串一样得到选择的文字,得到或设置文字,设置文本字段是否可编辑以及连同我们从
在线参考书中找到的相关方法。下面的例子将证明文本字段的其它功能;我们能注意到方法名是显而易见
的:
//: TextField1。java
// Using the text field control
import java。awt。*;
import java。applet。*;
public class TextField1 extends Applet {
Button
b1 = new Button(〃Get Text〃);
384
…………………………………………………………Page 386……………………………………………………………
b2 = new Button(〃Set Text〃);
TextField
t = new TextField(〃Starting text〃; 30);
String s = new String();
public void init() {
add(b1);
add(b2);
add(t);
}
public boolean action (Event evt; Object arg) {
if(evt。target。equals(b1)) {
getAppletContext()。showStatus(t。getText());
s = t。getSelectedText();
if(s。length() == 0) s = t。getText();
t。setEditable(true);
}
else if(evt。target。equals(b2)) {
t。setText(〃Inserted by Button 2: 〃 + s);
t。setEditable(false);
}
// Let the base class handle it:
else
return super。action(evt; arg);
return true; // We've handled it here
}
} ///:~
有几种方法均可构建一个文本字段;其中之一是提供一个初始字符串,并设置字符域的大小。
按下按钮 1 是得到我们用鼠标选择的文字就是得到字段内所有的文字并转换成字符串 S。它也允许字段被编
辑。按下按钮2 放一条信息和字符串 s 到Text fields,并且阻止字段被编辑(尽管我们能够一直选择文
字)。文字的可编辑性是通过 setEditable() 的真假值来控制的。
13。6 文本区域
“文本区域”很像文字字段,只是它拥有更多的行以及一些引人注目的更多的功能。另外你能在给定位置对
一个文本字段追加、插入或者修改文字。这看起来对文本字段有用的功能相当不错,所以设法发现它设计的
特性会产生一些困惑。我们可以认为如果我们处处需要“文本区域”的功能,那么可以简单地使用一个线型
文字区域在我们将另外使用文本字段的地方。在Java 1。0 版中,当它们不是固定的时候我们也得到了一个文
本区域的垂直和水平方向的滚动条。在Java 1。1 版中,对高级构建器的修改允许我们选择哪个滚动条是当前
的。下面的例子演示的仅仅是在Java1。0 版的状况下滚动条一直打开。在下一章里我们将看到一个证明 Java
1。1版中的文字区域的例程。
//: TextArea1。java
// Using the text area control
import java。awt。*;
import java。applet。*;
public class TextArea1 extends Applet {
Button b1 = new Button(〃Text Area 1〃);
Button b2 = new Button(〃Text Area 2〃);
Button b3 = new Button(〃Replace Text〃);
Button b4 = new Button(〃Insert Text〃);
TextArea t1 = new TextArea(〃t1〃; 1; 30);
385
…………………………………………………………Page 387………………………
快捷操作: 按键盘上方向键 ← 或 → 可快速上下翻页 按键盘上的 Enter 键可回到本书目录页 按键盘上方向键 ↑ 可回到本页顶部!
温馨提示: 温看小说的同时发表评论,说出自己的看法和其它小伙伴们分享也不错哦!发表书评还可以获得积分和经验奖励,认真写原创书评 被采纳为精评可以获得大量金币、积分和经验奖励哦!