XML 用户界面语言(XUL)开发简介
原文:http://www.ibm.com/developerworks/cn/education/xml/x-xulintro/index.html
介绍:
XUL 是经过测试的真正的应用程序框架。事实上,最近发布的 Firefox 3.0 不仅仅是由 XUL 构建的,但它提供了一个 XUL 运行时环境,允许任何 Firefox 用户运行其他 XUL 应用程序。在本教程,您开始使用 XUL 进行编程,并学习一些帮助您开发 XUL 应用程序的工具。当您的 Web 开发技术得到提高时,您可以构建一个基于 XUL 的博客编辑器,并通过它使用 XUL 构建桌面应用程序。
开始之前本教程适用于对桌面开发感兴趣又不想学习太多新技术的有经验的 Web 开发人员。XUL(发音与 cool 类似)使运用 Web 开发技能构建桌面应用程序变得很容易。它提供了丰富的 UI 部件集,这些工具使用的是所有 Web 开发人员都很熟悉的语法。使用 XUL,可以直接与 HTML 混合使用并可大量使用 JavaScript。 XUL 是一种基于 XML 的语言,因此需要对 XML(特别是 XML 名称空间)很熟悉。XUL 建立在我们熟悉和喜欢的 Web 技术之上:HTML、JavaScript 和 CSS。如果想有效地使用 XUL,需要对这些技术非常熟悉。使用 XPCOM 可以在很大程度上提高 XUL 应用程序的功能。这是一种跟分布式计算技术(例如 CORBA/IDL 和 COM)类似的技术。如果熟悉这些技术,在学习 XPCOM 时将会有所帮助,但并不做硬性要求。 关于本教程在本教程中,您将了解以下内容:
先决条件XUL 完全是开源的。为了使用 XUL 进行开发以及实践本教程的示例,您需要下载:
回页首 XUL 是什么?XUL 表示 XML 用户界面语言(XML User Interface Language)。因为是 XML,所以 XUL 是一种声明性语言。XUL 提供了丰富的 UI 部件集合,这些部件可以加速开发进程。它是一种跨平台的语言,可以在 Linux? 上构建自己的 XUL 应用程序,然后在 Windows? 上运行该程序。XUL 大量使用了 Web 技术,例如 JavaScript 和 Cascading StyleSheets(CSS)。甚至可以将 HTML 直接集成到 XUL 应用程序中。深入了解 XUL 以及它为何成为备受关注的开发平台。 XUL 历史回放XUL 与 Netscape 和 Mozilla Foundation 是同义词。Netscape 浏览器最初的意图是作为一个跨平台浏览器。这需要将 UI 框架从特定于操作系统的布局和控制部件中分离出来。还需要一种方法让这些分离出的元素和本地进程(用于网络连接、文件 I/O 等)进行通信。要构建跨平台且能够和 HTML 和 Web 元素协作的应用程序,所有这些元素都非常必要。这个框架被叫做 XPFE(跨平台前端),用于构建 Netscape Communicator 以及该系列的其他产品,如它的电子邮件和聊天客户端。 您可能对 Netscape 公司的发展历程比较熟悉。该公司在 1995 年的 IPO 标志着 dot-com 辉煌的开始。直到 1998 年,公司虽然在财政上不太顺利,但是取得了一些重要的技术成就。这些成就的核心就是 Mozilla 项目。这是从 Netscape Communicator 4.0 的代码在获得开源许可之后公开发行开始的。 事实证明这个代码库难于开发和维护,但是幸运的是,在他们的计划中也有好的方面。Netscape 不但让现有的 Communicator 开放源代码,他们的下一代布局引擎代码也是开源的。这个布局引擎将会成为 Gecko。它的一个重要功能是支持声明性的、基于 XML 的 UI 语言,也就是 XUL。 XUL:XML、JavaScript 和 CSSXUL 是为 Gecko 引擎构建的私有 UI 语言。它受到基于 Gecko 的 Web 浏览器开发人员的青睐。这是因为它是构建在标准技术(例如 XML、JavaScript 和 CSS)之上的。 XUL 是一种 XML 语言。这使得它的语法很简单,并且容易阅读(和解析)!XUL 跟 HTML 有很多相似之处,因此 Web 开发人员对它很熟悉。它甚至允许 XHTML 元素与 XUL 部件混合使用。XUL 通过许多方式证明了 XML 非常适合于创建 UI 语言,由一些类似语言的出现也能看出这一点。例如,来自 Adobe? 的 MXML(Adobe Flex 框架中的 UI 语言)和来自 Microsoft? 的 XAML(.NET 3.0 和 Windows Presentation Foundation 中的 UI 语言)。 当然,声明性编程存在固有的局限性。它不可避免地需要一些强制性编程。XUL 直接支持 JavaScript,而不是发明一种新语言或者创建一些基于 XML 的语法。现在 JavaScript 作为一种编程语言经常受到负面的评价。JavaScript 被认为是一种适合于非编程人员的语言,并且充满了特定于浏览器的扩展和特性。然而,JavaScript 是一种强大的语言,它是 Web 应用程序开发的中坚力量。毕竟,JavaScript 是 Ajax 中的 “J”。它是一种函数性编程语言,但很容易以过程或面向对象的方式使用它。XUL 把 JavaScript 当作一种桌面编程语言,并将其放在最前面的位置。XUL 也非常依赖 JavaScript 中的 DOM 实现 — 毕竟,XUL 是基于 XML 的。 XUL 中用于 Web 开发的另一个重要方面是 CSS。CSS 已经成为向 Web 页面添加样式的事实标准。它的层叠特性具有强大的功能和灵活性,这种特性允许将样式应用于对象和子对象,同时也允许这些子对象根据需要重写样式。XUL 将这种功能和灵活性应用到桌面应用程序中。 JavaScript 和 CSS 的另一个共同之处是,其行为都会根据浏览器的不同而变化。浏览器嗅探在 JavaScript 中非常常见,因此程序员可以在基于用户使用的浏览器类型和版本的多个实现中编写相同的函数。在 CSS 中条件样式的使用也具有相同的特性。如果做过许多 Web 开发,就可能遭遇过这些浏览器怪僻。如果属于这种情况,您将会喜欢上使用 XUL 编程。为什么呢? 因为使用 XUL 时只需要考虑一个浏览器。就像在全世界都使用 Firefox 的情况下开发 Web 应用程序。 XPCOM 和 XBL如果已经熟悉了 XUL,但可能又忘记了 XUL 的两个重要功能:XPCOM 和 XBL。别担心,现在将介绍这些技术,而且本教程稍后还显示它的功能。您将会看到如何使用这些技术来增强所开发的应用程序的功能。首先介绍 XPCOM。 XPCOM(即跨平台组件模块)与 CORBA 和 Microsoft COM 类似。XPCOM 允许用一个 IDL 模块(就像 Java? 或者 C# 代码中的接口或者 Web 服务的 WSDL)表示代码库。用其他语言编写的应用程序可以通过 XPConnect 解释程序来引用这个代码库。例如,Gecko 引擎的几乎所有功能在 XPCOM 中都是公开的。这个引擎是用 C++ 编写的,但是,有了 XPCOM,您就可以使用任何具备 XPCOM 支持的语言来利用库中的任何资源,例如 JavaScript、C++、Perl 和 Python。例如,Gecko 的网络库是一个 XPCOM 组件,因此可以从 JavaScript 访问它。 XPCOM 可以使您利用来自许多库的功能。这是 XUL 中重复出现的一个主题:为开发人员提供他们需要的所有构建块,并让他们专注于构建自己的应用程序。并且,XUL 提供了一个大型的 UI 部件库。它也提供了一种方法,此方法使用 XML 绑定语言(XML Binding Language,XBL)来更改这些部件的行为和功能。使用 XBL 可以为部件创建自己的行为,然后将这种行为绑定到部件。如何绑定呢?这是 XBL 一个很聪明的部分。使用一个 CSS 选择器来进行绑定。使用选择器选择一个或多个部件,然后用特定的 CSS 特性 广泛采用 XUL从纯技术的立场上看,XUL 是一个用于跨平台应用程序开发的有趣框架。也许仅仅是一个有趣的技术框架。但是另一个产品证明它不仅仅是一个技术框架,那就是 Firefox。XUL 是通过重写 Netscape 发展起来的,这种重写是通过让 Netscape 更加模块化来实现的。相同的思想也应用在了 Mozilla Firefox Web 浏览器开发中。 创建 Firefox 的动机是构建使用 Gecko 引擎支持的精简浏览器。这只有使用 Gecko 的模块化结构才可能实现。结果被证明是成功的。至 2008 年 9 月,Firefox 已占到了 19% 的全球市场份额,拥有 1.4 亿用户。它还获得了主流媒体(例如,Forbes 和 PC World)的好评。 Firefox 最初的成功很大程度上来自于它的快速呈现引擎(Gecko)以及它在安全方面的优越性。Firefox 持续获得成功和采用的一个原因在于它的扩展系统。该扩展系统使开发人员能够轻松地在 Firefox 之上构建专有功能。针对 Firefox 的扩展已变得非常流行。在编写此教程时,Mozilla 的官方扩展列表上已有超过 1800 种扩展。而且,许多其他的扩展没有收录到 Mozilla 的官方列表中。 Firefox 扩展的关键在于,创建拥有强大功能的扩展非常简单。这很简单:可以用 XUL 编写 Firefox 扩展,就像 Firefox UI 一样。它们可以利用 XUL 强大的覆盖特性。有了覆盖,就可以定位一部分现有的 UI 组件,并插入自己制作的新的 UI 组件。图 1 显示安装了一些扩展的 Firefox。 图 1. 带有扩展的 Firefox5 个红色的矩形表示来自扩展的 UI 元素。导航工具栏内包含一个大工具栏和 3 个按钮。此外,状态栏上还有几个图标。单击这些图标将打开大的对话框,每个对话框都将用户界面和菜单、选项卡等关联起来。这表明 Firefox 扩展本身就是强大的应用程序,因为它们使用 Firefox,所以就使用了 XUL 作为开发平台。 超越 Firefox:XULRunnerFirefox 将 XUL 奉献给了数百万用户。但 XUL 并不仅仅是一个创建 Firefox 及其扩展的技术。Firefox 的用于电子邮件的姊妹应用程序是 Mozilla Thunderbird。这个程序也是用 XUL 编写的,并且拥有一个活跃的扩展库,通过 XUL 覆盖实现。尽管它没有 Firefox 那么流行,但是它拥有 5 百万活动用户。机会在于您的 ISP 提供了一些指令,如果他们为您提供了电子邮件帐户,那么这些指令可用来将 Thunderbird 设置为该帐户的一个 IMAP 或者 POP 客户机。XUL 并不局限于 Mozilla 项目。它也被设计为一个框架,用于跨平台桌面应用程序的开发。然而,像 Firefox 和 Thunderbird 这样的应用程序是围绕 Gecko 引擎构建的。它们需要 Gecko 引擎来呈现 HTML 页面和 HTML 电子邮件,但是 Gecko 引擎也呈现了它们的 UI。一般而言,大多数桌面应用程序不需要呈现 HTML,因此它们也不需要 Gecko 引擎。但是没有 Gecko,它们如何使用 XUL 呢?答案就在于 XULRunner。XULRunner 在 Gecko 引擎之外提供纯 XUL 运行时环境,从而延续了 Gecko 的模块化特性。这允许您构建应用程序代码中直接包含 XULRunner 的应用程序。 Firefox 3.0构建运行在 XULRunner 上的应用程序时,一个不足之处是需要在应用程序中包含 XULRunner。这导致应用程序大概增加了 12MB。这对于像 Songbird 这样的媒体播放器来说不算什么。毕竟现在大多数媒体播放器都比较大。对于像 Joost 这样的流视频应用程序来说也不算什么。毕竟,流视频需要快速连接,因此对大多数 Joost 用户来说,额外的 12MB 可能很快就能下载下来。但是对于许多应用程序来说,XULRunner 运行时跟应用程序本身一样大,或者更大。这使得 XULRunner 不再那么有吸引力。 然而,您不再需要将 XUL 应用程序和 XULRunner 捆绑在一起。因为 Firefox 3.0 已经构建在 XULRunner 之上。Firefox 和 XULRunner 使用相同的核心库和 libxul,这允许任何 XUL 应用程序使用 Firefox 作为 XUL 运行时,而不是 XULRunner。到 2008 年 9 月份为止,全世界一共有 1.4 亿 Firefox 用户。在这些用户当中,有 68% 已经更新到 Firefox 3.0。这相当于超过 9500 万用户已经安装了 XUL 运行时。即您的 XUL 的潜在使用者多达 9500 万。这个事实也适用于 Firefox 开发人员。在本教程后面的详细论述中,您将看到,只需添加 回页首
XUL 开发我们已经了解了 XUL 的起源和发展情况。更重要的是,已经明白了可以用 XUL 和它提供给开发人员的有利时机来做什么。我希望您现在已经迫不及待想要进行 XUL 开发了。首先,您将设置一个 XUL 开发环境。 XUL 开发环境在了解 XUL 时已经注意到,可以使用 XUL 做许多不同的事情。因此,没有绝对适合的 XUL 开发环境。一般而言,您将会基于 XUL 的不同用途配置环境。 基本原理首先,XUL 是一种基于 XML 的 UI 语言。要创建 XUL 文件,只需要能够创建 XML 文件。您或许想编写一些脚本,以使应用程序具有交互性,因此需要编写一些 JavaScript。要创建 XML 和 JavaScript 文件,不需要特定的编译器。XUL 运行时将会解释这些文件。但是,您还需要做一些事情。 也许最重要的一点是 XUL 应用程序的目录结构。在本教程中将会创建一个称为 xulblogger 的应用程序。图 2 显示了该程序的目录结构。 图 2. XUL 应用程序的目录结构图 2展示了 3 个重要文件。首先是 application.ini。这个文件必须放在应用程序的根目录下。它最重要的用途是告诉 XUL 运行时它需要什么版本的运行时,如清单 1 所示。 清单 1. application.ini 文件[App] Vendor=developerworks Name=xulblogger Version=0.2 BuildID=20080924 [Gecko] MinVersion=1.9 下一个重要的配置文件是 chrome.manifest。这个文件必须放在 chrome 目录中。通常需要在 chrome 目录中包含一个子目录,用于存放所有的 XUL 文件。可以根据自己的喜好为其命名。它在清单 2 中叫做 “xulblogger”,但是许多应用程序将其命名为 “content”。chrome.manifest 用于告诉 XUL 运行时如何找到您的文件。清单 2 显示了 chrome.manifest 的一个示例。 清单 2. chrome.manifest 文件content xulblogger file:xulblogger/
可以看到,这个文件只包含一行简单的配置。最后一个重要的文件是 prefs.js。此文件必须放在 /defaults/preferences 目录下。它告诉运行时首先需要载入什么样的 XUL 文件,如清单 3 所示。 清单 3. prefs.js 文件pref("toolkit.defaultChromeURI","chrome://xulblogger/content/home.xul");
您或许还注意到了 extensions 和 updates 目录。不用担心这两个目录,XUL 运行时将会自动创建它们。 关于这里描述的结构,还有一个需要注意的事情是:XUL 应用程序通常是通过创建顶级目录的一个 JAR 文件来部署的。如果安装了 Java 开发工具,可以使用 Java jar 命令来创建 JAR,或者可以直接将目录压缩,然后将其扩展名由 .zip 更改为 .jar。 Eclipse 和 XUL作为一个有经验的开发人员,您可能已经知道 Integrated Development Environment (IDE) 的价值。您可能考虑 IDE 是否可用于 XUL。这有大量的选择,有几个可用的 XUL IDE 构建在非常通用的 Eclipse 平台之上。对于 XML、JavaScript 和 CSS 编辑,XULBooster(参见参考资料)使用流行的 Eclipse Web Tools Platform。它还使用 XULRunner 来执行应用程序,并且连接到 XULRunner 进行调试。图 3 显示了 XULBooster 的屏幕截图。 图 3. XULBooster另一个选项是 Spket。这可以作为独立的 IDE 获得,也可以作为 Eclipse 插件获得(参见参考资料)。这不是特定于 XUL 的 IDE,但它提供了几个对 XUL 开发人员非常有用的特性。Spket 提供 XUL 和 XBL 控件,以及 XUL 和 JavaScript 的详细代码。图 4 展示了 Spket 的屏幕截图。 图 4. Spket IDE不管选择什么样的编辑器,您最终都需要运行代码。再声明一下,您有很多选择,其中一些还使用 Firefox。 运行 XUL 应用程序可以选择 3 种方式来运行 XUL 应用程序:
回页首
博客编辑器XUL 开发环境准备就绪后,就可以使用 XUL 构建一个示例应用程序了。我们将会构建一个简单的博客编辑器,这个编辑器可以创建并预览博客条目。也可以在本地保存博客条目并在以后重新载入。编辑器将会使用 XUL 作为用户界面,并使用 JavaScript 来完成每件事情。开始之前,先设置用户界面。 博客编辑器的用户界面这是最令开发人员憎恶的应用程序部分。创建用户界面非常繁琐,但是 XUL 使这变得很容易。XUL 有许多控件,用于创建部件和指定布局。请看清单 4 中定义的一个简单 UI。 清单 4. XUL(/chrome/xulblogger/home.xul)中定义的 UI<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
<xul:window id="xulblogger" title="Create Blog Entry" orient="horizontal"
align="start" xmlns="http://www.w3.org/1999/xhtml" height="1000"
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<xul:script src="blog.js"/>
<xul:script src="json.js"/>
<xul:vbox height="800">
<xul:hbox>
<xul:label value="Name of entry"/>
<xul:textbox id="name" multiline="false" cols="70"/>
<xul:label value="Signature"/>
<canvas id="canvas" width="300" height="10"
style="border:1px solid gray;">
</canvas>
</xul:hbox>
<xul:textbox id="entry" multiline="true" rows="10" cols="80"/>
<xul:hbox>
<xul:label value="Tags"/>
<xul:textbox id="tags" cols="80" multiline="false"/>
<xul:button id="saveBtn" class="btnClass" label="Save" />
<xul:button id="previewBtn" label="Preview" onclick="preview()"/>
</xul:hbox>
<xul:hbox>
<xul:label value="Publish Date"/>
<xul:datepicker type="grid" value="{new Date()}"/>
</xul:hbox>
<div id="preview"></div>
</xul:vbox>
<xul:script src="canvas.js"/>
<xul:script>read();</xul:script>
</xul:window>
这是一个很简单的 UI。XUL vbox 和 hbox 组件使布局变得很简单。按从左到右的顺序,vbox 在垂直方向上依次排列各个对象,而 hbox 在水平方向排列各个对象。UI 有 2 个标签、3 个文本框(包括一个多行文本框)和 2 个按钮。这些都是非常直观的代码;即使您以前没有见过 XUL,也能知道这些代码的用途。该 UI 还使用了几个更高级的控件。它使用了一个 datepicker 控件。这是在 Firefox 3 中引入的新控件。注意使用 JavaScript 表达式初始化 datepicker 的开始日期(值属性)的方式。此外,还需要注意使用户可以在 XUL 控件内部绘制的画布控件,该控件使他们能够对博客发布进行电子签名。仔细研究这个控件的工作原理。 画布控件画布控件并不是一个真正的 XUL 控件。它是一个 HTML 控件。虽然 Safari 浏览器引入了画布元素,但 Firefox 仍然支持它???Web Hypertext Application Technology Working Group (WHATWG) 使画布成为将要推出的 HTML 5 规范的一部分。不过,当前所有版本的 Internet Explorer? 都没有支持它,包括 Internet Explorer 8 的 beta 版。因此,大部分 Web 开发人员不能利用这一特性,除非他们的用户不使用 Internet Explorer。然而,进行 XUL 开发时,这并不是什么问题。通过 XUL 应用程序,您可以使用任何 Firefox 支持的 HTML、CSS 和 JavaScript。它只在 XUL 应用程序的内部执行,而不是 Web 浏览器。因此,您不用担心它不能在 Internet Explorer 上使用。 画布控件允许应用程序在控件内部绘制。这种绘制通常使用 JavaScript 自动完成。同样,要使用户能够进行绘制,您可以使用 JavaScript 监听带有该控件的用户交互,然后使用画布 API 进行绘制。在这个应用程序中,canvas.js 脚本完成了所有这些任务。清单 5 展示了该文件的内容。 清单 5. JavaScript 画布控件代码// courtesy of Mozilla's Mark Finkler
// http://starkravingfinkle.org/blog
function Scribbler_init() {
Scribbler.init();
}
var Scribbler = {
canvas : null,ctx : null,drawing : false,init : function() {
this.canvas = document.getElementById("canvas");
this.ctx = this.canvas.getContext("2d");
this.drawing = false;
this.canvas.addEventListener("mousedown",this.doDrawStart,false);
addEventListener("mouseup",this.doDrawStop,false);
this.canvas.addEventListener("mousemove",this.doDrawUpdate,false);
},doDrawStart : function(event) {
// Calculate the position of the mouse over an element. To do this,subtract
// the position of the element the mouse is over from the mouse position. The
// element's position can be determined from its boxObject.
// We are using the <box> container as a XUL wrapper
// for the HTML <canvas>
var offsetX = (event.clientX - event.target.parentNode.boxObject.x);
var offsetY = (event.clientY - event.target.parentNode.boxObject.y);
Scribbler.ctx.beginPath();
Scribbler.ctx.moveTo(offsetX,offsetY);
Scribbler.drawing = true;
},doDrawStop : function(event) {
if (Scribbler.drawing) {
Scribbler.ctx.closePath();
Scribbler.drawing = false;
}
},doDrawUpdate : function(event) {
if (Scribbler.drawing) {
// Calculate the position of the mouse over an element. To do this,subtract
// the position of the element the mouse is over from the mouse position. The
// element's position can be determined from its boxObject.
// We are using the <box> container as a XUL wrapper
// for the HTML <canvas>
var offsetX = (event.clientX - event.target.parentNode.boxObject.x);
var offsetY = (event.clientY - event.target.parentNode.boxObject.y);
Scribbler.ctx.lineTo(offsetX,offsetY);
Scribbler.ctx.stroke();
}
},doDrawClear : function() {
this.ctx.fillStyle = "#fff";
this.ctx.fillRect(0,this.canvas.width,this.canvas.height);
}
};
Scribbler_init();
清单 5中的代码创建了一个 运行应用程序您可以使用 XULRunner 或 Firefox 启动这个应用程序。图 5 是博客编辑器 UI 的屏幕截图。 图 5. 博客编辑器 UI 您或许在清单 4中注意到,有一个叫做 preview 的 HTML div。这是一个用来预览博客条目的 HTML 区域。它让用户进入正常的 HTML,然后单击 preview 按钮查看外观。但是如何将编辑器中的 HTML 转换成在 preview 区域上显示的 HTML。回头看看 XUL 代码,您将看到一个 清单 6.
|