技术开发 频道

高级 Synth

  【IT168 技术文章】文将深入透视 Synth 外观,它是 Java 5.0 中为 Swing 引入的最新内容。通过为 Java UI 编程引入“皮肤”的概念,Synth 使开发人员可以为应用程序创建和部署定制的外观。软件工程师 Michael Abernethy 将带您从头开始逐步构建一个具有 synth 外观的应用程序,让您充分了解 Synth 的概念。阅读本文之后,您应该可以在短时间内创建具有专业外观的 UI。

  就在 Sun 一如既往地试图“再次引入 Java Desktop”之际,Java UI 开发人员的抱怨之词亦已表面化:要创建完全定制的外观实在太难。这样做不仅要花费太多的时间,并且 Swing UI 代码的编写和文档的编制也极为不堪,常常是乱杂一气,缺乏规划。为了创建完整的外观,开发人员需要继承 Metal 外观的 39 个类,或者继承 Basic 外观的 60 个类。谁想通过重写整个包来改变应用程序呈现外观的方式呢?用 Swing 创建定制外观有多难,通过下面的事实同样可窥见一斑:在很多开发人员为开源项目添砖加瓦的时代,Internet 上可用的自定义 Swing 外观几乎是凤毛麟角 —— 总共大约是 20 个,其中少数在 SourceForge.net 上。

  美丽只是肤浅的东西

  进入 Synth,Sun 希望它能使应用程序外观的个性化过程变得容易。Synth 的目标很简单 —— 让开发人员不必编写任何代码就可以创建新的外观。这似乎是个不错的解决方案。程序员一般没有突出的艺术才华,而图形设计人员通常也不是 Java 编程专家。Synth 把对外观的所有描述从代码中分离出来,而将其放入外部的 XML 文件和图像文件中,为上述问题提供了大快人心的解决之道。这种完全在外部文件中描述的外观被称作皮肤(skin)。

  Sun 的皮肤概念并不是什么创新。例如,Winamp 有数百种皮肤,Firefox 也有几十种皮肤,这些皮肤很容易创建,只需更改一个 XML 文件即可。想像一下,仅仅修改一个 XML 文件,就能快速、容易地为 Java 应用程序创建一个外观。再想想这样一来的结果 —— 几百个互不相同的 Swing 外观。Java UI 开发人员当然有理由欢呼了。

  本文将深入分析 Synth 外观,向您展示创建一个完整的外观或皮肤所需知道的一切。您会看到一个带有示例皮肤的应用程序,这个应用程序使用了 Synth 所有重要的概念。然后,我会逐步剖析这个皮肤,在构建 XML 文件的过程中,一一教会您 Synth 的各个概念。

  本文最后一节将尽力回答开发人员关于 Synth 性能、bug 和缺陷以及 Synth 在省时方面的表现等种种问题。阅读本文之后,您应该会愿意拥护 Synth 作为外观解决方案,并准备马上使用它来创建自己的 Swing 外观。

  Synth 基础

  Synth 是一个白板(tabula rasa)外观 —— 一块完全空白的画布,表现为一个完全空白的面板(panel),只有在 XML 文件中定义了组件时,它才会显示东西。一旦定义了组件,在应用程序上设置 Synth 外观就再容易不过了,如清单 1 所示:

  清单 1. 设置 Synth 外观

1 SynthLookAndFeel synth = new SynthLookAndFeel();
2    synth.load(SynthFrame.class.getResourceAsStream("demo.xml"), SynthFrame.class);
3    UIManager.setLookAndFeel(synth);

  但是,对于 Synth,最重要的是要理解它是 XML 代码,而不是 Java 代码。虽然 Synth XML 格式一开始看上去比较吓人,但实际上很简单。如果使用 KISS (Keep It Simple Stupid)这道符咒,您可以快速地创建一个 XML 文件,并得到一个新的、可以运行的外观。

  考虑到 KISS 指令,我将首先介绍 Synth XML 文件的主要构件 —— <style>标签。<style>标签包含描述一个组件的式样的所有信息,例如颜色、字体、图像文件、状态,以及一些特定于组件的属性。虽然一个<style>标签可以描述多个组件,但构建 Synth 文件的最简便方法是为每个 Swing 组件创建一个式样。

  创建好式样之后,便可以将式样链接到一个组件。<bind>标签通知 Synth 引擎将一个已定义的式样链接到一个组件,如清单 2 所示。这样的组合便完全创建了组件的新外观。

  清单 2. 将一种式样链接到一个组件

1 <style id="textfield">
2    // describe colors, fonts, and states
3 </style>
4 <bind style="textfield" type="region" key="Textfield"/>
5 <style id="button">
6    // describe colors, fonts, and states
7 </style>
8 <bind style="button" type="region" key="Button"/>

        关于 <bind> 标签,要注意的一点是:<bind> 标签中的 key 属性映射到javax.swing.plaf.synth.Region 类中的常量。Synth 引擎使用这些常量将式样与一个实际的 Swing 组件链接。简单的组件,例如 JButtonJTextField,使用一个常量。有些更复杂的组件,例如 JScrollBarJTabbedPane,则有多个常量,用于不同的部分。

        我建议您在更熟悉 Synth 格式并且能够设置 XML 中的继承模型之前,使用每个组件一种式样(one-style-per-component)的设置。这种结构虽然没有利用所有 XML 的分层结构功能,但它是最容易设置、编写代码和调试的。

       在处理 Synth XML 文件时,还有一点很重要,并不是任何形式都是合法的。如果有输入错误,或者在 XML 中使用了不正确的属性,这些错误只有当外观装载期间抛出一个运行时异常时才能发现。解决方法:在将 XML 文件发布给客户之前,对其进行测试。

0
相关文章