J2SE 5.0专题 之 用户接口
作者(枯木)
1.1. 引子
“从Java诞生至今已有9年时间,而从第二代Java平台J2SE算起也有5个年头了。在这样的背景下,将下一个版本的版本号从1.5改为5.0可以更好的反映出新版J2SE的成熟度、稳定性、可伸缩性和安全性。” Sun公司如是解释Java的这次意义深远的变革。众所周知Sun公司从发布Java以来,对Java的每一次变更可谓是小心翼翼,特别是经历了版本一到版本二的变更后,Java一直就停留在比较稳定的时期,这对于一个处于IT行业前沿中的主流技术确实令人难以想象。
可能对于象Sun这种以技术起家的公司来说,从骨子里就透出一种“不鸣则已,一鸣惊人”的气质。Java从版本一到二的飞跃中已经初露端倪,那么这次Java的变更又会带来什么呢?从它发布3个月以来的各方评价,亦可探知一二。其他暂且不论,单从这次变更涉及的面上看就知,这绝非产于一朝一夕,从宏观上语言特性到具体的API,从Java底层的虚拟机到高层的核心库,几乎无一例外的加入了这次变更。如此之大的变更,即便是我这个对Java语言认识不深的人,也能从中略窥一二,但不敢深论,只是学有小得,顺道写些想法,与各位共同学习交流。以下我将对J2SE(TM) 5.0中的用户接口(UI)部分做一些简要的介绍。
1.2. 综述
Java一直以来在桌面系统中表现的并不是很成功,究其原因主要是在UI方面表现的不尽如人意,虽然在理论上Sun公司对UI同样做出了无所不能的承诺,可是一个真正成功的设计不能只停留在理论层面上,而要真正受开发人员认可,在市场中得到青睐才能算得上成功,可Java在UI方面两者都做的不是很优秀。这次J2SE(TM) 5.0在UI方面作了大幅度的调整,大有弥补这方面缺陷的势头,对于抢夺在桌面系统的领地是志在必得。关于这次调整的相关评论信息,可以在网上查阅,这里限于篇幅暂且不论。下面将对J2SE(TM) 5.0涉及UI方面的调整做一些介绍,其内容包括:
1、国际化
2、Java 声音技术
3、Java 2D(TM)技术
4、图像 I/O
5、AWT
6、Swing
上面的各个主题由于本人水平及篇幅所限可能无法一一详述,有些在这里只能稍作介绍,作为一个引子,其余的还望读者更多地去思考,去探索。
1.3. 国际化
Java语言作为第一种支持国际化的语言,在Internet从一开始就具有其他语言无与伦比的国际化的本质特性:用Unicode来编写所有的字符串。可是理论与实际总是不能完全谋和的,因为Unicode本身也在不断变化。
在J2SE(TM) 5.0中,主要的变化是对java.lang, java.text, java.util.regex等包进行调整,使整个字符处理基于Unicode4.0的标准之上,同时加强了对增补字符的支持(欲了解更多信息请参照:《Supplementary Characters in the Java Platform》By Norbert Lindenberg and Masayoshi Okutsu,)。另外这些调整,已经比较全面地解决了越南等东南亚国家的文字读写及显示问题,虽然并没有经过大范围的测试。查看Java所支持的语言及相应的版本信息可以采用以下代码进行查询。
import java.util.*;
import java.text.*;
public class Test{
public static void main(String[] args) {
//输出JVM支持的语言
Locale locale[] = DateFormat.getAvailableLocales();
System.out.println("======本地系统支持语言:======== ");
for (int i = 0; i < locale.length; i++) {
System.out.println(locale[i].toString() + "\t" + locale[i].getDisplayName());
}
//输出 JVM 默认属性
System.out.println("======系统属性======== ");
System.getProperties().list(System.out);
}
}
在桌面系统中,J2SE(TM) 5.0的这次变更主要表现在成功地处理了逻辑字体的多语言文本支持,例如,如果您在泰国语环境中,但已经安装了韩国语的字体,就可以呈现泰国语和韩国语,这只需通过java.util.Locale类进行相应的操作即可方便地达到应有的目标。还同时解决了在 Windows 2000/XP 中,AWT调用 Unicode API的问题。这样在J2SE(TM) 5.0中就可以运用它自带的一些文本组件进行文本处理,而不用受到 Windows locale 设置的限制,增强了Java跨平台的功能,使Java真正能够相对地独立于Windows平台。例如,AWT 文本组件可以在梵文书写系统中接受和显示文本,并不用关心 Windows locale 的设置,而仅仅依靠Java程序内部的处理机制。
另外,在java.nio包中也增强了对I/O传输国际化的支持。这在核心库中已经有所介绍了,这里就不在重复了。
1.4. Java声音技术
声音技术在Java的领域里应该算是一个比较专业,对于很多非专业的开发者可能会很陌生,读者如果希望对这方面知识进行更全面的了解,还请参阅《Java(TM) Sound Programmer Guide》。以下仅列出J2SE(TM) 5.0在声音处理技术中改进的部分:
1、 现在端口可在所有平台上使用(RFE 4782900)。
2、 现在 MIDI 设备 I/O 可在所有平台上使用(RFE 4812168 和 RFE 4782924)。
3、 在所有平台上实现了优化的直接音频访问 (RFE 4908240 和 RFE 4908879)。在提供本机混合的系统上(如具有硬件混合的 Linux ALSA、启用的 Solaris Mixer 和 Windows DirectSound),默认情况下启用了它。
4、 新的实时序列与所有 MIDI 设备一起工作,并允许无限地进行传送(RFE 4773012)。
5、 sound.properties 配置文件允许选择默认设备(RFE 4776511)。 有关更多信息,请参见 MidiSystem 和 AudioSystem。
6、 MidiDevices 可以查询连接的接收器和传送器(RFE 4931387, MidiDevice.getReceiver 和 MidiDevice.getTransmitter 方法)。
7、 AudioFormat、AudioFileFormat 和 MidiFileFormat 现在具有一些属性来允许进一步描述和限定格式 (RFE 4925767 和 RFC 4666845)。
8、 一组易用的方法集允许更加容易地从 AudioSystem 检索行(RFE 4896221)。
序列接口是用循环方法扩展的,它可以在 MIDI 序列的特定部分进行无缝循环。(RFE 4204105)。
9、Java Sound 不再禁止 VM 退出(bug 4735740)。
1.5. Java 2D技术及图像 I/O
J2SE(TM) 5.0在Java 2D技术及图像I/O方面在应用方面并没有进行过多的更改,多数还是保持在原来的状态,但是很多更改的部分在Java语言中扮演着重要的角色,而且其中的更改部分仍然代表着Java语言一贯坚持的前进方向。在J2SE(TM) 5.0之前所有针对图象操作 在BufferedImage内增加了预读功能,并适时地针对图象处理加入了一些硬件加速的处理方法,如:Image类中的setAccelerationPriority and getAccelerationPriority。
另外,还添加了 2D 特性包括扩展的 Linux 和 Solaris 打印机支持、用于从文件和流中创建字体的新方法和与 VolatileImages 和图像的硬件压缩有关的新方法。对文本呈现代码的大量更改大大提高了它的强健性、性能和可伸缩性。其他性能工作包括在 Linux 和 Solaris 上使用 OpenGL 进行硬件加速呈现(默认情况下是禁用的)。以上性能的引入将使Java语言在桌面系统中的应用变得更加简单实用。
而在图像 I/O方面,增加了具有针对 BMP 和 WBMP 格式的阅读器和编写器,即可以用XML语言进行控制来处理相应的图像,增强了整个系统的重用性。
1.5.1. AWT与Swing
J2SE(TM) 5.0版本提供了许多 AWT 增强功能和修补程序,其中包括一些客户经常要求的一些增强功能和修补程序。特别是新的 MouseInfo 类使得可以决定桌面上鼠标的位置。新的 Window 方法使得可以根据平台来指定最近创建的窗体(或帧)的默认位置。另一个窗口增强功能使得可以保证窗体(或帧)总是处在最上层(对于 Solaris/Linux 上的一些窗体处理器,这种特性是不能工作的)。在数据转换方面,新的 DropTargetDragEvent API 使得在拖动过程中可以让目标访问传送的数据。这些API的引入不管从哪一方面都在很大程度上增强了Java语言的易用性。
Swing在这次Java的变更中扮演着一个极其重要的角色,它的变更已经不仅仅停留在更改几个API,而是在实现的理念里添加进了新的实现元素,这势必会影响Java在桌面系统应用里UI的构架设计。Swing是Java在桌面系统中最主要的应用技术,从其出现伊始就广受人们的关注,而且Sun公司也一直将它作为Java在桌面系统的主流技术进行推广。在J2SE(TM) 1.4.2 中, Swing 提供了两种外观:XP 和 GTK。但这没有到此就停止,在J2SE(TM) 5.0中Swing为我们提供了另外两种外观:Synth —— 可切换皮肤的外观和 Ocean —— 针对 Metal 的新主题。摒弃了1.4默认的陈旧的Metal外观之后,J2SE(TM) 5.0引入了一个全新的Ocean外观。以Sun公司 SwingSet2演示程序作为向导,比较 Meta 外观的原有主题 Steel 与Metal 外观的 Ocean 主题(如下图)。另外,我们不得
Metal 的 Steel 主题 Metal 的 Ocean 主题
不提起的是Synth,它是一个完整的外观,而不是一个主题,它针对的并不是程序员,而是界面设计人员,让他们不必掌握Java知识便能够进行相应界面的选择定制。采用了Synth后,我们不能从现有外观或主题派生子类、修改字体或颜色,而是通过转载不同的XML 文件以达到对相应界面的控制。其实现步骤包括将程序外观设置成Synth模式以及编辑相对应的XML文件。设置Synth外观模式,可以使用以下代码:
SynthLookAndFeel synth = new SynthLookAndFeel();
Class aClass = SynthTest.class;
InputStream is = aClass.getResourceAsStream("file1.xml");
synth.load(is, aClass);
UIManager.setLookAndFeel(synth);
对于 XML 中的大多数事情来说,文件的内容由文档类型定义(DTD)描述。只要在 XML 文件中描述组件,然后把文件传给 SynthLookAndFeel 实例的 load() 方法,应用程序的外观就会有所不同。以下是XML控制程序外观的代码:
<synth>
<style id="button">
<font name="Dotum" size="24" style="BOLD"/>
<state value="MOUSE_OVER">
<font name="System" size="48" style="ITALIC"/>
</state>
</style>
<bind style="button" type="region" key="Button"/>
</synth>
以下附上Synth的演示代码SynthTest.java,与其相对应的XML文件可选用上面的示例代码,将其更名为synth.xml即可:
import java.io.InputStream;
import java.text.ParseException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.UIManager;
import javax.swing.plaf.synth.SynthLookAndFeel;
public class SynthTest{
private static void createGUI(){
SynthLookAndFeel synth = new SynthLookAndFeel();
try {
Class classA = SynthTest.class;
InputStream in = classA.getResourceAsStream("synth.xml");
if (in == null) {
System.err.println("Unable to find theme configuration");
System.exit(-1);
}
synth.load(in, classA);
} catch (ParseException e) {
System.err.println("Unable to load theme configuration");
System.exit(-2);
}
try {
UIManager.setLookAndFeel(synth);
} catch (javax.swing.UnsupportedLookAndFeelException e) {
System.err.println("Unable to change look and feel");
System.exit(-3);
}
JFrame frame = new JFrame("Test Synth");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JButton button = new JButton("Hello Synth");
frame.add(button);
frame.setSize(400, 200);
frame.setVisible(true);
}
public static void main(String[] args){
javax.swing.SwingUtilities.invokeLater(new Runnable(){
public void run() {
createGUI();
}
});
}
}
除了外观的调整之外,J2SE(TM) 5.0已经添加了对 JTable的打印支持,这使得可以容易地获取 JTable 的漂亮打印副本。另外,在Java语言发展了多年后,J2SE(TM) 5.0终于实现了 JFrame.add() 等价于 JFrame.getContentPane().add()。
1.6. 结束语
以上介绍的内容仅仅与大家共同领略了J2SE(TM) 5.0所带来的新的UI元素,不图窥一斑而知全豹,但从中仍然能看出Java前进的步伐,愿Java一路走好!