Java编程思想第4版[中文版](PDF格式)-第126部分
按键盘上方向键 ← 或 → 可快速上下翻页,按键盘上的 Enter 键可回到本书目录页,按键盘上方向键 ↑ 可回到本页顶部!
————未阅读完?加入书签已便下次继续阅读!
for(int i = 0; i 《 q。length; i++)
tabbed。addTab((String)q'i''0';
makePanel((Class)q'i''1'));
add(tabbed; BorderLayout。CENTER);
tabbed。setSelectedIndex(q。length/2);
}
public static void main(String args'') {
Show。inFrame(new Tabbed();460;350);
}
} ///:~
再者,我们可以注意到使用的数组构造式样:第一个元素是被置放在卡片上的String,第二个元素是将被显
示在对应窗格上JPanel 类。在 Tabbed()构建器里,我们可以看到两个重要的 JTabbedPane 方法被使用:
addTab()插入一个新的窗格,setSelectedIndex()选择一个窗格并从它开始。(一个在中间被选中的窗格证
明我们不必从第一个窗格开始)。
当我们调用 addTab()方法时,我们为它提供卡片的 String 和一些组件(也就是说,一个 AWT 组件,而不是
一个来自AWT 的Jponent)。这个组件会被显示在窗格中。一旦我们这样做了,自然而然的就不需要更多
管理了——JTabbedPane 会为我们处理其它的任何事。
484
…………………………………………………………Page 486……………………………………………………………
makePanel()方法获取我们想创建的类 Class 对象和用newInstance()去创建并造型为JPanel (当然,假定那
些类是必须从JPanel 继承才能增加的类,除非在这一节中为程序例子的结构所使用)。它增加了一个包括类
名并返回结果的TitledBorder,以作为一个JPanel 在 addTab()被使用。
当我们运行程序时,我们会发现如果卡片太多,填满了一行,JTabbedPane 自动地将它们堆积起来。
13。19。16 Swing 消息框
开窗的环境通常包含一个标准的信息框集,允许我们很快传递消息给用户或者从用户那里捕捉消息。在
Swing 里,这些信息窗被包含在JOptionPane 里的。我们有一些不同的可能实现的事件(有一些十分复
杂),但有一点,我们必须尽可能的利用 static JOptionPane。showMessageDialog()和
JOptionPane。showConfirmDialog()方法,调用消息对话框和确认对话框。
13。19。17 Swing 更多的知识
这一节意味着唯一向我们介绍的是 Swing 的强大力量和我们的着手处,因此我们能注意到通过库,我们会感
觉到我们的方法何等的简单。到目前为止,我们已看到的可能足够满足我们UI 设计需要的一部分。不过,这
里有许多有关Swing 额外的情况——它有意成为一全功能的 UI 设计工具箱。如果我们没有发现我们所需要
的,请到SUN 公司的在线文件中去查找,并搜索WEB。这个方法几乎可以完成我们能想到的任何事。
本节中没有涉及的一些要点:
■更多特殊的组件,例如JColorChooser;JFileChooser;JPasswordField;JHTMLPane (完成简单的HTML 格式
化和显示)以及JTextPane (一个支持格式化,字处理和图像的文字编辑器)。它们都非常易用。
■Swing 的新的事件类型。在一些方法中,它们看起来像违例:类型非常的重要,名字可以被用来表示除了
它们自己之外的任何事物。
■新的布局管理:Springs & Struts 以及BoxLayout
■分裂控制:一个间隔物式的分裂条,允许我们动态地处理其它组件的位置。
■JLayeredPane 和JInternalFrame 被一起用来在当前帧中创建子帧,以产生多文件接口(MDI )应用程序。
■可插入的外观和效果,因此我们可以编写单个的程序可以像期望的那样动态地适合不同的平台和操作系
统。
■自定义光标。
■JToolbar API 提供的可拖动的浮动工具条。
■双缓存和为平整屏幕重新画线的自动重画批次。
■内建“取消”支持。
■拖放支持。
13。20 总结
对于AWT 而言,Java 1。1 到 Java 1。2 最大的改变就是Java 中所有的库。Java 1。0 版的AWT 曾作为目前见过
的最糟糕的一个设计被彻底地批评,并且当它允许我们在创建小巧精致的程序时,产生的GUI “在所有的平
台上都同样的平庸”。它与在特殊平台上本地应用程序开发工具相比也是受到限制的,笨拙的并且也是不友
好的。当Java 1。1 版纳入新的事件模型和 Java Beans 时,平台被设置——现在它可以被拖放到可视化的应
用程序构建工具中,创建GUI 组件。另外,事件模型的设计和 Bean 无疑对轻松的编程和可维护的代码都非常
的在意(这些在 Java 1。0 AWT 中不那么的明显)。但直至GUI 组件-JFC/Swing 类-显示工作结束它才这
样。对于Swing 组件而言,交叉平台GUI 编程可以变成一种有教育意义的经验。
现在,唯一的情况是缺乏应用程序构建工具,并且这就是真正的变革的存在之处。微软的Visual Basic 和
Visual C++需要它们的应用程序构建工具,同样的是Borland 的Delphi 和C++构建器。如果我们需要应用程
序构建工具变得更好,我们不得不交叉我们的指针并且希望自动授权机会给我们所需要的。Java 是一个开放
的环境,因此不但考虑到同其它的应用程序构建环境竞争,而且Java 还促进它们的发展。这些工具被认真地
使用,它们必须支持Java Beans。这意味着一个平等的应用领域:如果一个更好的应用程序构建工具出现,
我们不需要去约束它就可以使用——我们可以采用并移动到新的工具上工作即可,这会提高我们的工作效
率。这种竞争的环境对应用程序构建工具来说从未出现过,这种竞争能真正提高程序设计者的工作效率。
485
…………………………………………………………Page 487……………………………………………………………
13。21 练习
(1)创建一个有文字字段和三个按钮的程序片。当我们按下每个按钮时,使不同的文字显示在文字段中。
(2)增加一个复选框到练习 1 创建的程序中,捕捉事件,并插入不同的文字到文字字段中。
(3)创建一个程序片并增加所有导致action()被调用的组件,然后捕捉他们的事件并在文字字段中为每个组
件显示一个特定的消息。
(4)增加可以被 handleEvent()方法测试事件的组件到练习3 中。过载handleEvent()并在文字字段中为每个
组件显示特定的消息。
(5)创建一个有一个按钮和一个TextField 的程序片。编写一个handleEvent() ,以便如果按钮有焦点,输入
字符到将显示的TextField 中。
(6)创建一个应用程序并将本章所有的组件增加主要的帧,包括菜单和对话框。
(7)修改TextNew。java,以便字母在t2 中保持输入时的样子,取代自动变成大写。
(8)修改CardLayout1。java 以便它使用Java 1。1 的事件模型。
(9)增加Frog。class 到本章出现的清单文件中并运行jar 以创建一个包括Frog 和 BangBean 的JAR 文件。现
在从SUN 公司处下载并安装 BDK 或者使用我们自己的可激活Bean 的程序构建工具并增加 JAR 文件到我们的环
境中,因此我们可以测试两个 Bean 。
(10)创建我们自己的包括两个属性:一个布尔值为“on”,另一个为整型“level”,称为Valve 的Java
Bean 。创建一个清单文件,利用jar 打包我们的 Bean ,然后读入它到beanbox 或到我们自己的激活程序构建
工具里,因此我们可以测试它。
(11)修改Menus。java,以便它处理多级菜单。这要假设读者已经熟悉了 HTML 的基础知识。但那些东西并不
难理解,而且有一些书和资料可供参考。
486
…………………………………………………………Page 488……………………………………………………………
第 14 章 多线程
利用对象,可将一个程序分割成相互独立的区域。我们通常也需要将一个程序转换成多个独立运行的子任
务。
象这样的每个子任务都叫作一个“线程”(Thread)。编写程序时,可将每个线程都想象成独立运行,而且
都有自己的专用CPU。一些基础机制实际会为我们自动分割CPU 的时间。我们通常不必关心这些细节问题,
所以多线程的代码编写是相当简便的。
这时理解一些定义对以后的学习狠有帮助。“进程”是指一种“自包容”的运行程序,有自己的地址空间。
“多任务”操作系统能同时运行多个进程(程序)——但实际是由于CPU 分时机制的作用,使每个进程都能
循环获得自己的CPU 时间片。但由于轮换速度非常快,使得所有程序好象是在“同时”运行一样。“线程”
是进程内部单一的一个顺序控制流。因此,一个进程可能容纳了多个同时执行的线程。
多线程的应用范围很广。但在一般情况下,程序的一些部分同特定的事件或资源联系在一起,同时又不想为
它而暂停程序其他部分的执行。这样一来,就可考虑创建一个线程,令其与那个事件或资源关联到一起,并
让它独立于主程序运行。一个很好的例子便是“Quit ”或“退出”按钮——我们并不希望在程序的每一部分
代码中都轮询这个按钮,同时又希望该按钮能及时地作出响应(使程序看起来似乎经常都在轮询它)。事实
上,多线程最主要的一个用途就是构建一个“反应灵敏”的用户界面。
14。1 反应灵敏的用户界面
作为我们的起点,请思考一个需要执行某些CPU 密集型计算的程序。由于 CPU “全心全意”为那些计算服
务,所以对用户的输入十分迟钝,几乎没有什么反应。在这里,我们用一个合成的applet/application (程
序片/应用程序)来简单显示出一个计数器的结果:
//: Counter1。java
// A non…responsive user interface
package c14;
import java。awt。*;
import java。awt。event。*;
import java。applet。*;
public class Counter1 extends Applet {
private int count = 0;
private Button
onOff = new Button(〃Toggle〃);
start = new Button(〃Start〃);
private TextField t = new TextField(10);
private boolean runFlag = true;
public void init() {
add(t);
start。addActionListener(new StartL());
add(start);
onOff。addActionListener(new OnOffL());
add(onOff);
}
public void go() {
while (true) {
try {
Thread。currentThread()。sleep(100);
} catch (InterruptedException e){}
if(runFlag)
t。setText(Integer。toString(count++));
487
…………………………………………………………Page 489……………………………………………………………
}
}
class StartL implements ActionListener {
public void actionPerformed(ActionEvent e) {
go();
}
}
class OnOffL implements ActionListener {
public void actionPerformed(ActionEvent e) {
runFlag = !runFlag;
}
}
public static void main(String'' args) {
Counter1 applet = new Counter1();
Frame aFrame = new Frame(〃Counter1〃);
aFrame。addWindowListener(
new WindowAdapter() {
public void windowClosing(WindowEvent e) {
System。exit(0);
}
});
aFrame。add(applet; BorderLayout。CENTER);
aFrame。setSize(300;200);
applet。init();
applet。start();
aFrame。setVisible(true);
}
} ///:~
在这个程序中,AWT 和程序片代码都应是大家熟悉的,第 13章对此已有很详细的交待。go()方法正是程序全
心全意服务的对待:将当前的 count (计数)值置入TextField (文本字段)t,然后使count 增值。
go() 内的部分无限循环是调用sleep()。sleep()必须同一个 Thread (线程)对象关联到一起,而且似乎每个
应用程序都有部分线程同它关联(事实上,Java 本身就是建立在线程基础上的,肯定有一些线程会伴随我们
写的应用一起运行)。所以无论我们是否明确使用了线程,都可利用Thread。currentThread()产生由程序使
用的当前线程,然后为那个线程调用sleep()。注意,Thread。currentThread()是 Thread 类的一个静态方
法。
注意 sleep()可能“掷”出一个 InterruptException (中断违例)——尽管产生这样的违例被认为是中止线
程的一种“恶意”手段,而且应该尽可能地杜绝