Java编程思想第4版[中文版](PDF格式)-第110部分
按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
加入一个前缀“add”。比如addMouseMotionListener()。
下表是对接收器接口的一个总结:
接收器接口 接口中的方法
Listener interface M e t h o d s i n i n t e r f a c e
w / a d a p t e r
A c t i o n L i s t e n e r actionPerformed(ActionEvent)
AdjustmentListener a d j u s t m e n t V a l u e C h a n g e d (
A d j u s t m e n t E v e n t )
ponentListener ponentHidden(ponentEvent)
ponentAdapter ponentShown(ponentEvent)
ponentMoved(ponentEvent)
ponentResized(ponentEvent)
ContainerListener ponentAdded(ContainerEvent)
ContainerAdapter ponentRemoved(ContainerEvent)
F o c u s L i s t e n e r f o c u s G a i n e d ( F o c u s E v e n t )
412
…………………………………………………………Page 414……………………………………………………………
F o c u s A d a p t e r f o c u s L o s t ( F o c u s E v e n t )
K e y L i s t e n e r k e y P r e s s e d ( K e y E v e n t )
K e y A d a p t e r k e y R e l e a s e d ( K e y E v e n t )
k e y T y p e d ( K e y E v e n t )
M o u s e L i s t e n e r m o u s e C l i c k e d ( M o u s e E v e n t )
M o u s e A d a p t e r m o u s e E n t e r e d ( M o u s e E v e n t )
m o u s e E x i t e d ( M o u s e E v e n t )
m o u s e P r e s s e d ( M o u s e E v e n t )
m o u s e R e l e a s e d ( M o u s e E v e n t )
MouseMotionListener m o u s e D r a g g e d ( M o u s e E v e n t )
MouseMotionAdapter m o u s e M o v e d ( M o u s e E v e n t )
W i n d o w L i s t e n e r w i n d o w O p e n e d ( W i n d o w E v e n t )
W i n d o w A d a p t e r windowClosing(WindowEvent)
w i n d o w C l o sed(WindowEvent)
windowActivated(WindowEvent)
windowDeactivated(WindowEvent)
windowIconified(WindowEvent)
windowDeiconified(WindowEvent)
I t e m L i s t e n e r itemStateChanged(ItemEvent)
T e x t L i s t e n e r textValueChanged(TextEvent)
1。 用接收器适配器简化操作
在上面的表格中,我们可以注意到一些接收器接口只有唯一的一个方法。它们的执行是无轻重的,因为我们
仅当需要书写特殊方法时才会执行它们。然而,接收器接口拥有多个方法,使用起来却不太友好。例如,我
们必须一直运行某些事物,当我们创建一个应用程序时对帧提供一个WindowListener,以便当我们得到
windowClosing()事件时可以调用 System。exit(0)以退出应用程序。但因为WindowListener 是一个接口,我
们必须执行其它所有的方法即使它们不运行任何事件。这真令人讨厌。
为了解决这个问题,每个拥有超过一个方法的接收器接口都可拥有适配器,它们的名我们可以在上面的表格
中看到。每个适配器为每个接口方法提供默认的方法。(WindowAdapter 的默认方法不是windowClosing(),
而是System。exit(0)方法。)此外我们所要做的就是从适配器处继承并过载唯一的需要变更的方法。例如,
典型的WindowListener 我们会像下面这样的使用。
class MyWindowListener extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System。exit(0);
}
}
适配器的全部宗旨就是使接收器的创建变得更加简便。
但所谓的“适配器”也有一个缺点,而且较难发觉。假定我们象上面那样写一个 WindowAdapter :
class MyWindowListener extends WindowAdapter {
public void WindowClosing(WindowEvent e) {
System。exit(0);
}
}
表面上一切正常,但实际没有任何效果。每个事件的编译和运行都很正常——只是关闭窗口不会退出程序。
您注意到问题在哪里吗?在方法的名字里:是 WindowClosing(),而不是windowClosing()。大小写的一个简
单失误就会造成一个崭新的方法。但是,这并非我们关闭窗口时调用的方法,所以当然没有任何效果。
413
…………………………………………………………Page 415……………………………………………………………
13。16。3 用 Java 1。1 AWT 制作窗口和程序片
我们经常都需要创建一个类,使其既可作为一个窗口调用,亦可作为一个程序片调用。为做到这一点,只需
为程序片简单地加入一个main()即可,令其在一个 Frame (帧)里构建程序片的一个实例。作为一个简单的
示例,下面让我们来看看如何对Button2New。java 作一番修改,使其能同时作为应用程序和程序片使用:
//: Button2NewB。java
// An application and an applet
import java。awt。*;
import java。awt。event。*; // Must add this
import java。applet。*;
public class Button2NewB extends Applet {
Button
b1 = new Button(〃Button 1〃);
b2 = new Button(〃Button 2〃);
TextField t = new TextField(20);
public void init() {
b1。addActionListener(new B1());
b2。addActionListener(new B2());
add(b1);
add(b2);
add(t);
}
class B1 implements ActionListener {
public void actionPerformed(ActionEvent e) {
t。setText(〃Button 1〃);
}
}
class B2 implements ActionListener {
public void actionPerformed(ActionEvent e) {
t。setText(〃Button 2〃);
}
}
// To close the application:
static class WL extends WindowAdapter {
public void windowClosing(WindowEvent e) {
System。exit(0);
}
}
// A main() for the application:
public static void main(String'' args) {
Button2NewB applet = new Button2NewB();
Frame aFrame = new Frame(〃Button2NewB〃);
aFrame。addWindowListener(new WL());
aFrame。add(applet; BorderLayout。CENTER);
aFrame。setSize(300;200);
applet。init();
applet。start();
aFrame。setVisible(true);
}
} ///:~
414
…………………………………………………………Page 416……………………………………………………………
内部类WL 和main()方法是加入程序片的唯一两个元素,程序片剩余的部分则原封未动。事实上,我们通常
将WL 类和main()方法做一结小的改进复制和粘贴到我们自己的程序片里(请记住创建内部类时通常需要一
个外部类来处理它,形成它静态地消除这个需要)。我们可以看到在 main()方法里,程序片明确地初始化和
开始,因为在这个例子里浏览器不能为我们有效地运行它。当然,这不会提供全部的浏览器调用 stop()和
destroy()的行为,但对大多数的情况而言它都是可接受的。如果它变成一个麻烦,我们可以:
(1) 使程序片句柄为一个静态类(以代替局部可变的main()),然后:
(2) 在我们调用 System。exit()之前在 WindowAdapter。windowClosing()中调用applet。stop()和
applet。destroy()。
注意最后一行:
aFrame。setVisible(true);
这是Java 1。1 AWT 的一个改变。show()方法不再被支持,而 setVisible(true)则取代了show()方法。当我
们在本章后面部分学习 Java Beans 时,这些表面上易于改变的方法将会变得更加的合理。
这个例子同样被使用TextField 修改而不是显示到控制台或浏览器状态行上。在开发程序时有一个限制条件
就是程序片和应用程序我们都必须根据它们的运行情况选择输入和输出结构。
这里展示了 Java 1。1 AWT 的其它小的新功能。我们不再需要去使用有错误倾向的利用字符串指定
BorderLayout 定位的方法。当我们增加一个元素到Java 1。1 版的BorderLayout 中时,我们可以这样写:
aFrame。add(applet; BorderLayout。CENTER);
我们对位置规定一个BorderLayout 的常数,以使它能在编译时被检验(而不是对老的结构悄悄地做不合适的
事)。这是一个显著的改善,并且将在这本书的余下部分大量地使用。
2。 将窗口接收器变成匿名类
任何一个接收器类都可作为一个匿名类执行,但这一直有个意外,那就是我们可能需要在其它场合使用它们
的功能。但是,窗口接收器在这里仅作为关闭应用程序窗口来使用,因此我们可以安全地制造一个匿名类。
然后,main()中的下面这行代码:
aFrame。addWindowListener(new WL());
会变成:
aFrame。addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System。exit(0);
}
});
这有一个优点就是它不需要其它的类名。我们必须对自己判断是否它使代码变得易于理解或者更难。不过,
对本书余下部分而言,匿名内部类将通常被使用在窗口接收器中。
3。 将程序片封装到JAR 文件里
一个重要的 JAR 应用就是完善程序片的装载。在Java 1。0 版中,人们倾向于试法将它们的代码填入到单个的
程序片类里,因此客户只需要单个的服务器就可适合下载程序片代码。但这不仅使结果凌乱,难以阅读(当
然维护也然)程序,但类文件一直不能压缩,因此下载从来没有快过。
JAR 文件将我们所有的被压缩的类文件打包到一个单个儿的文件中,再被浏览器下载。现在我们不需要创建
一个糟糕的设计以最小化我们创建的类,并且用户将得到更快地下载速度。
仔细想想上面的例子,这个例子看起来像 Button2NewB,是一个单类,但事实上它包含三个内部类,因此共
有四个。每当我们编译程序,我会用这行代码打包它到一个JAR 文件:
jar cf Button2NewB。jar *。class
这是假定只有一个类文件在当前目录中,其中之一来自Button2NewB。java (否则我们会得到特别的打包)。
现在我们可以创建一个使用新文件标签来指定 JAR 文件的HTML 页,如下所示:
Button2NewB Example Applet
415
…………………………………………………………Page 417……………………………………………………………
与HTML 文件中的程序片标记有关的其他任何内容都保持不变。
13。16。4 再研究一下以前的例子
为注意到一些利用新事件模型的例子和为学习程序从老到新事件模型改变的方法,下面的例子回到在本章第
一部分利用事件模型来证明的一些争议。另外,每个程序包括程序片和应用程序现在都可以借助或不借助浏
览器来运行。
1。 文本字段
这个例子同 TextField1。java 相似,但它增加了显然额外的行为:
//: TextNew。java
// Text fields with Java 1。1 events
import java。awt。*;
import java。awt。event。*;
import java。applet。*;
public class TextNew extends Applet {
Button
b1 = new Button(〃Get Text〃);
b2 = new Button(〃Set Text〃);
TextField
t1 = new TextField(30);
t2 = new TextField(30);
t3 = new TextField(30);
String s = new Stri