内容


Java 2 用户界面

Java UI 是怎样演变的以及它的前景如何?

Comments

在 Java 2 平台发行之前,抽象窗口工具包(Abstract Window Toolkit,AWT)是 Java 平台的图形功能的范围。例如 Swing 等各种技术都是作为可选的扩展被引入的。在 Java 2 平台上,这些扩展中的大部分都可以在平台的核心中找到它们的一席之地,成为 Java 基础类(Java Foundation Classes,JFC)的一部分。JFC 指的是包含在 Java 2 平台内的一整套图形和用户界面技术,包括 AWT 和 Swing 等。在本文中,我们将讨论 JFC 的每个主要组件,并讨论一些可选的扩展。

JFC 的核心:Swing

Swing 是一个带有一套丰富组件的 GUI 工具包,它组成了 JFC 的用户界面功能的核心部分。它不仅是 AWT 所提供的组件的替代品,并且在这些组件的基础上有了很大进步。

当集成有优先权时

在 JDK 首次发行时,与本机平台的集成被认为具有优先权,于是 AWT 提供了一些组件,这些组件使用各平台的本机组件(在 Java 编程术语中,这些被称为 重量级组件)来实现。例如,在 UNIX 平台上, java.awt.Button 类是用窗口小部件 Motif PushButton 实现的。

相同的 Java 应用程序在每个平台上都有不同的外观,但本意是不同的实现在功能上是等同的。当然,这也是问题开始的地方。在简单的界面里,这种等同是真的。但随着复杂性的增加,情况就不一样了,这只是因为组件的不同,而且在某些情况下,不管修正了多少错误,并且 AWT 的部件被重写了多少次,它们总会表现得有一点不同。

由于将优先权赋予集成而产生的另一个问题是功能性问题。AWT 只提供了有限的一套组件,是因为“最小公分母”方法 ― 只有当一个特殊的组件或功能在每个平台上都可用的时候才能够被提供。一个典型的示例就是鼠标键。在以前的 JDK 1.0.2 中,是无法区分鼠标键的点击的,因为 Macintosh 只有一个鼠标键,所以其它的每个平台都要表现得好像自己也只支持一个鼠标键一样。

语言自身已经变得不只是一种平台了,GUI 也正在朝着在所有平台上都有相同的外观和行为这种方向转变。为了实现这个目标,本机组件必须尽量地丢弃。但是,显然一些本机代码还是必需的。如果不包含 X System Window 的调用,您就不能在 UNIX 上显示一个窗口。

现在来看一下 Swing,它使用 AWT 的一个子集来实现这个目标,这个子集包括基本画图操作和 java.awt 包中的某些类(包括 ContainerWindowPanel DialogFrame )。

所有可能的方法中最好的

Swing 没有完全遵循“Java 语言作为一个平台”的路线。相反,它通过提供一个可以返回本机平台的桥梁,把两种方法的精华部分结合起来了。

建立这个桥梁的机制被称为 可插式 Look-and-Feel(它很接近主题的概念,在 linux 社区中非常流行)。每一个 Swing 组件都有一个自己的功能模型和一个独立的外观(look-and-feel),这可以预先设置或在运行时更改。

Swing 为 Windows 平台和 Motif 平台分别提供一个 Java look-and-feel(以前称为 Metal),同时为 Macintosh 平台提供一个 Java look-and-feel(作为额外选项)。平台的 look-and-feel 不像 AWT 一样使用平台的本机组件。相反,它们使用 轻量级组件,有和本机组件一样的外观。这对于功能性来说是好的,但在外观上或行为上总有一些不同,所以复杂的界面永远不会和使用本机组件的界面完全相同。

另外,您可以制作自己的 look-and-feel。当您为高度专门化的应用程序制作一个 look-and-feel,或为一系列应用程序提供一个共同的 look-and-feel 时,这是一种强大的功能。

图 1、图 2 和图 3 展示了每一个主要的 look-and-feel 的屏幕。

图 1. Java look-and-feel
图 1. Java look-and-feel
图 1. Java look-and-feel
图 2. Windows look-and-feel
图 2. Windows look-and-feel
图 2. Windows look-and-feel
图 3. Motif look-and-feel
图 3. Motif look-and-feel
图 3. Motif look-and-feel

要了解在发行版 1.4 中 Swing 有什么新特性,您可以跳到本文最后一部分, 1.4 版本中对 UI 做的更改

独立于平台的拖放

JDK 1.1 增加了一个通用机制,这种机制放在 java.awt.datatransfer 包中,实现了应用程序之间和应用程序内部的数据传输,以及对系统剪贴板的操作能力。

Java 2 版本引入了 java.awt.dnd 包。此包建立在数据传输的机制上,提供了拖放功能,这些功能可以在一个单独的 Java 应用程序内或两个 Java 应用程序之间以一种平台无关的方式执行。为了集成本机平台的拖放功能,它也可以以一种平台 相关的方式运行。

使用拖放(Drag and Drop,DND)API 很具有挑战性,因为它要操作在很高的抽象度上来支持它工作的不同方式,同时也因为它被设计成操作被 java.awt.datatransfer.Transferable 接口所指定的任意数据类型。让我们看一个示例。

DND API 如何工作

首先,需要一个 DragSource 对象来初始化拖放操作。该对象被用于创建一个 DragGestureRecognizer ,它规定标明拖动操作开始点的事件。例如,在一个特定组件上按下鼠标左键然后移动鼠标。

系统一识别到此动作,可利用 DragSource 对象通过要传输的信息来定义操作的开始点。

下一步,拖动操作的有效目的地可通过向 DropTarget 对象传送一个组件或者调用 Component 的新的 setDropTarget() 方法来定义。

实现 DropTargetListener 接口的类可用来响应拖放操作中可能出现的各种事件。主要事件是放操作,一个 DropTargetDropEvent 对象被传送给该操作。可向该对象查询被拖动的数据的类型。

侦听器可以拒绝或者接受拖动并传输数据,完成拖放操作。

方便残疾人士:辅助选项(Accessibility)

Java 应用程序配备有 JFC Accessibility API(JFC 辅助选项 API),所以可以被具有各种能力的用户访问,包括视力、听力或行动不便的用户。这些可能包括不能分辨视觉或听觉信号或者不能操作定位设备。

辅助选项支持的两大重要功能就是屏幕读取器和屏幕放大镜。屏幕读取器允许用户通过创建界面的 off-screen 表示,并将其传送到一个语音合成器或盲文终端来与 GUI 进行交互。屏幕放大镜提供一个屏幕的放大窗口,典型情况下是正常大小的 2 到 16 倍。它们通常不断跟踪指针的移动和输入焦点的改变,然后相应地调整放大的窗口。另外,象平滑字体这样的技术可能会用于生成更清晰的图像。

Java Accessibility Bridge(Java 辅助选项 Bridge)

一些主机系统,如 Microsoft Windows,提供它们自己的辅助选项功能。缺省情况下,Java 应用程序并不完全支持它们。例如,对于本机应用程序,屏幕放大器探测输入焦点何时转换到另一个不同的用户界面组件(例如通过使用 Tab 键),然后调整放大的屏幕部分,来显示当前拥有输入焦点的组件。

然而,Swing 应用程序使用的是轻量级的组件,操作系统将这些组件作为图像处理,而不作为离散的组件来处理。这就意味着屏幕放大器不能象本机应用程序那样在输入焦点中跟踪发生的改变。

这正好就是面向 Windows 的 Java Accessibility Bridge 所要解决的问题。它在与轻量级组件有关的事件和本机系统事件之间建立一个映射。使用这个 Bridge,支持 Accessibility API 的 Java 应用程序就可以与 Windows 辅助选项支持完全集成。

本文结束处的 参考资料提供了更多与辅助选项有关的参考资料的链接。

从简单到先进:Java 2D

在 Java 2 平台之前,语言中的图形功能相当简单,仅限于单像素厚度的实线;少数几个几何图形(如椭圆、弧和多边形);和基本的画图功能。随着 Java 2D API(它包含一个真正的功能集)的出现,所有的一切都改变了。

这个 API 的核心是由 java.awt.Graphics2D 类提供的,该类是 java.awt.Graphics 的一个子类。API 的其它部分由 java.awt 层次结构中的其它包提供,包括 java.awt.colorjava.awt.fontjava.awt.geom

java.awt.Graphics2D 类

这个类是 java.awt.Graphics (该类在 Java 2 发行前就提供图形功能)的一个子类。这样安排的原因是:向后兼容。组件的着色还是通过调用它们的 paint() 方法,它使用一个 Graphics 对象。

尽管在语言的当前版本中,这个对象真是一个 Graphics2D 对象。这意味着, paint() 方法可以将 Graphics 对象作为一个 Graphics 对象使用(使用旧的画图方法),或者将其强制转换成 Graphics2D 对象。如果使用第二种选择,就可以使用 2D API 的所有附加功能。

java.awt.geom 包

java.awt.geom 包提供一些有关二维几何的类,如 Arc2DLine2DRectangle2D Ellipse2DCubicCurve2D 。其中每一个都是抽象类,他们都是两个名为 DoubleFloat 的非抽象内部类(它们是抽象外部类的子类)。

这些类允许各种几何图形建立在双精度或浮点精度的坐标系上。例如, newEllipse2D.Float(x,y,w,h) 将在 (x,y) 点上构造一个以宽为 w、高为 h 的矩形为边界的椭圆,其中 x、y、wh都为浮点值。

在这个包里还有 AffineTransform 类,它是组成 2D API 的核心元素。仿射转换指的是平行线在转换后还保持平行。这种类型的转换示例包括如下的操作:平移、旋转、缩放、剪切或者这些操作的组合。每一个转换都可以用一个 3x3 的矩阵来表示,该矩阵规定转换的源点和目标点之间的映射。

AffineTransform 类的实例可以直接从一个浮点值的矩阵中创建,尽管通常情况下是通过规定一个或多个平移、旋转、缩放或剪切操作来创建。多数情况下是使用双精度值,并且角度是用弧度来度量的(而不是 Arc2D 类中使用的度)。

文本着色

Java 2D API 的文本功能也相当强大。它们包括:

  • 使用抗锯齿处理和微调(hinting)以达到更好的输出质量
  • 可以使用系统安装的所有字体
  • 可以将对图形对象的操作(旋转、缩放、着色、剪切等等)应用到文本上。
  • 支持向字符串添加内嵌属性(如字体、尺寸、深浅,甚至图像)
  • 支持双向文本(启用从右到左的字符顺序,就象您在阿拉伯语和希伯来语中可能遇到的一样)
  • 第一光标和第二光标能够浏览同时包含从右到左和从左到右字符顺序的文本。
  • 先进的字体度量功能,超过旧的 java.awt.FontMetrics 类中的相应功能
  • 排版功能可以实现单词换行和调整多行文本

Java 2D 工作的一个示例

清单 1 包含一个使用部分 Java 2D 方法的基本示例的代码,加上几个其它的方法。这是一个完整的程序,但只是接触了 2D API 所提供的功能的皮毛。(输出请参见图 4)。

清单 1. 一个简单的 Java 2D 示例
import java.awt.*;
import java.awt.geom.*;
public class j2d extends Frame {
    public static void main(String args[]) { new j2d(); }
    public j2d() {
        setSize(220,180);
        setVisible(true);
    }
    public void paint(Graphics g) {
        // Obtain a Graphics2D object
        Graphics2D g2 = (Graphics2D)g;
        // Set the rendering quality.
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
            RenderingHints.VALUE_ANTIALIAS_ON);
        // define a linear colour gradient
        GradientPaint gp = new GradientPaint(0, 60, Color.red,
                                             0, 120, Color.yellow);
        Ellipse2D r = new Ellipse2D.Float(30, 60, 160, 60);
        g2.setPaint(gp);
        g2.fill(r);
        // set rotation
        g2.transform(AffineTransform.getRotateInstance(Math.PI/8));
        g2.setFont(new Font("Serif", Font.BOLD, 85));
        g2.setPaint(Color.blue);
        // set compositing rule with transparency
        g2.setComposite(AlphaComposite.getInstance(
                                       AlphaComposite.SRC_OVER, 0.5f));
        g2.drawString("J2D",50,70);
    }
}
图 4. 清单 1 的输出
清单 1 的输出

要了解更多关于 Java 2D API 的参考资料,请参阅 参考资料

声音终于迎头赶上:Audio API(音频 API)

Java 语言每发行一个主要版本,都会给音频功能带来稳步的提高。JDK 的 1.1 发行版以前(包括 1.1 发行版)的版本中,可以在 java.applet 包中找到对 8 位单声道声音的基本支持。一个 AU 格式的音频剪辑可以用 URL 来载入,并且只有三个操作可以使用:播放、停止和循环。1.2 发行版中改进了这种情况。

从 8 位到 16 位

Java 2 第一个发行版(版本 1.2)集成了一个经 Beatnik 公司许可的新的声音引擎,提供对各种常用格式的 16 位立体声的支持,包括 AU、WAV、AIFF 和多种 MIDI 格式。

这个版本中还附加了新的静态方法 java.applet.Applet.newAudioClip() ,它使得在应用程序中使用声音更加容易,而不仅仅在 applet 中。然后,1.3 版本取得了巨大的进步。

Java Sound API(Java 声音 API)

平台的 1.3 版本取得了目前为止最大的进步。这个版本使用相同的 Beatnik 声音引擎及以前所有的功能,并增加了一个全新的 API ― Java Sound API。

Java Sound API 提供了一套扩展的音频功能,并可通过新的 javax.media.sound.sampledjavax.media.sound.midi 包来访问。

javax.media.sound.sampled 包包含从各种声源回放声音的类,和最多能混合 64 声道的类。每一个音频信号可以通过不同的方法进行控制和处理,比如在不同文件格式之间的转换,和对效果(如增益和回响)的使用。同时还支持输入源(例如麦克风)的音频捕捉。

javax.media.sound.midi 包提供 MIDI 功能,包括载入音色库和从 MIDI 数据中生成声音,以及回放 MIDI 序列。

遗漏了什么?硬件加速

Java 音频功能还缺乏一个重要的方面 ― 硬件加速。缺乏这种支持意味着不管您的声卡硬件性能多么优秀,这些功能都无法被使用。这样的结构确实带来了好的跨平台可移植性,但付出的代价是高 CPU 开销和较低的性能。

标准演示包中的 JavaSound 演示展示了 Java Sound API 的许多功能。要了解更多相关信息,请参阅 参考资料

自动化事件:AWT 机器人

1.3 版本中新加入的 java.awt.Robot 类被设计成在本机平台上生成输入事件。提供的操作包括:

  • 移动鼠标指针到屏幕上给定的位置
  • 生成鼠标键按下和释放事件
  • 生成键盘按下和释放事件

这种功能为测试自动化带来了全新的可能性。例如,一系列事件可以被一次性记录,然后以全自动的方式自动回放任意遍。其它的功能还提供了测试一个屏幕坐标的像素颜色的方法,甚至可以将屏幕上的一整块区域作为一个图像缓冲捕捉下来。

要了解 AWT 在 1.4 版中有什么新特性,您可以跳到本文的最后部分, 1.4 版本中对 UI 做的更改

多媒体选项:Java Media API(Java 媒体 API)

Java Media API 是一套涵盖广泛的多媒体技术领域的资源。其中,如 2D API 和 声音 API 是核心 J2SE 平台的一部分;其余的是目前可选的扩展,不过其中的一些技术在将来无疑会进入核心。这个领域的其它 API 还有 Java 3D、Advanced Imaging(高级图像处理)、Image I/O(图像 I/O)、Java Media Framework(JMF,Java 媒体框架)和 Speech(语音)。

Java 3D

Java 3D API 提供了一套面向对象的接口,支持一种简单的、高级的编程模型,让开发人员可以构建、着色和控制 3D 对象的行为和可视环境。

这个 API 包括一个详细的规范文档和 javax.media.j3djavax.vecmath 包的实现。

Advanced Imaging

这个规范所涵盖的操作将提高用户处理图像的能力。它包括的操作有对比度增强、剪切、缩放、几何弯曲和频率范围处理。

这种类型的功能可应用于各种领域,如天文学、医学图像处理、科学目视表示、气象学和摄影。

Image I/O

这种 API 定义了一种可读/写不同格式图像的可插式框架。这种新的 API 正在由 Java Community Process 设计。

Java Media Framework(JMF)

JMF 是一种 API,可以将音频、视频和其它基于时间的媒体整合到 Java 应用程序和 applet 中。这个可选的包扩展了 J2SE 平台的多媒体功能。

Speech

Java Speech API 允许开发人员将语音技术整合到 Java applet 和应用程序的用户界面中。这种 API 规定一个跨平台的接口来支持 命令―控制识别器、听写系统和语音合成器。

这个综合 API 被分成几个规范:

  • Java Speech API 规范(Java Speech API Specification,JSAPI)
  • Java Speech API 程序员指南
  • Java Speech API 语法格式规范(Java Speech API Grammar Format Specification,JSGF)
  • Java Speech API 标记语言规范(Java Speech API Markup Language Specification,JSML)

这个 API 没有 Sun 公司的参考实现,但是有许多第三方实现,包括 Speech for Java(可以从 IBM alphaWorks 获得),它使用 ViaVoice 来支持语音命令识别、听写和文本到语音的合成。

清单 2. 举例说明了 Java Speech API 中的语音合成。它还使用 JSML 来控制合成器朗读文本的方式(定义音高、速度、重音等等)。

清单 2. 合成和 JSML
import javax.speech.synthesis.*;
public class TrySpeech {
    public static void main(String args[]) {
        Synthesizer synthesizer = Central.createSynthesizer(null);
        synthesizer.allocate();
        try {
            synthesizer.speak("Hello I am a computer", null);
            synthesizer.speak(
                "Hello I am a <EMP>computer</EMP>", null);
            synthesizer.speak(
                "Hello I am a <PROS PITCH="+10%">computer</PROS>",
                null);
        } catch (Exception e) { e.printStackTrace(); }
    }
}

要了解 Speech API 另外的信息,请参阅 参考资料

1.4 版本中对 UI 做的更改

即将发行的发行版,版本 1.4(代号为 Merlin)将展示许多新功能,同时还对许多错误进行了必需的修正。我们将重点阐述其中的一些变化。

Swing 有什么新特性

Merlin 发行版将给 Swing 工具包带来广泛的提高。新功能包括:

  • 一个用于不确定时间的进度条,它将向用户说明操作,而不用确定完成的程度。在您预先不知道某些事会用掉多少时间时,这些组件将会很有用(例如建立网络连接)。
  • JSpinner 组件,它让用户使用箭头按钮在列表中滚动,从一个有序的列表中进行选择。
  • JFormattedTextField 组件,它让开发人员限制文本组件中允许的字符集。这个功能在输入日期和数字时非常有用。
  • 增强了新的 JTabbedPane 以允许可滚动的制表页。目前当制表页不适合全部放在一行时,它们就会溢出到多个行中去,这对于用户来说是非常糟糕的,因为在选择另一行的制表页时窗格就必须重新排列制表页。这里采用的另一种办法时将所有的制表页保持在一行,但是提供箭头按钮来实现沿着行的滚动。
  • Windows look-and-feel 的增强使其能够更紧密地匹配本机平台。这些增强包括为匹配 Windows 2000 而对外观所做的改变,比如标题栏的渐近填充,以及与 Windows 桌面更好的集成以响应用户对桌面设置的更改。
  • 大量的错误被修正,还有一些较小的增强,包括为 Swing 事件附加声音的功能。

AWT 得到一个新的焦点模型

在发行版 1.4 中 AWT 被赋予一种全新的焦点模型,很久以来这一直是个问题区域。现有的焦点模型非常令人头痛,因为它存在无数的错误,并且功能很少,比如不能查询当前哪个组件拥有焦点。产生问题的原因通常是:不同的平台处理输入焦点的方式不同,以及新的轻量级组件要求单独处理焦点所带来的复杂性。

新模型已经尽可能使用共享代码实现;平台相关的代码被最小化。新模型的核心是 java.awt.KeyboardFocusManager 类。这个类将提供公共 API 调用来查询和设置焦点状态的许多方面,比如当前哪个组件享有焦点,还有焦点遍历循环中组件的顺序。

最后一点:新的焦点模型与当前各个版本不是完全向后兼容的,所以现有的应用程序将需要彻底的测试。

其它 AWT 功能

用一个滚动轮作为鼠标中键的鼠标非常流行,所以增加了对它的支持。它采用的形式为,一个 新的 MouseWheelEvent 类、一个 MouseWheelListener 接口和一个新的 java.awt.Component 类的 addMouseWheelListener() 方法(和对应的 removeMouseWheelListener() 方法)。

增加了对 Headless Java. 的支持。这个增加意味着,在服务器上运行的 Java 应用程序在没有 GUI 环境的情况下也仍然能够使用 AWT,例如,在内存中创建图像以便通过网络发出。

最后,其它的更改包括对拖放功能的增强、创建无修饰框架的能力,以及众多错误的修正。


相关主题


评论

添加或订阅评论,请先登录注册

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Java technology
ArticleID=53301
ArticleTitle=Java 2 用户界面
publish-date=07162001