Vincent.Chan‘s Blog

常用链接

统计

积分与排名

网站

最新评论

XML 问题: GUI 和 XML 配置数据,第 2 部::Mozilla 项目和 XUL

级别: 中级

David Mertz, Browser, Gnosis Software, Inc.

2004 年 5 月 26 日

David 继续关于如何在 GUI 界面配置中使用 XML 的话题。他考察了 Mozilla 基于 XML 的用户界面语言(XUL),这种语言编写的应用程序完全不依赖所选择的底层操作系统。初看起来这似乎有点奇怪,但很快您就会看到该 Mozilla 项目为构建 GUI 提供了非常强大的工具,允许您开发范围广泛的用户界面。

在开始讨论那些并非所有 读者都熟悉的缩写字符串和奇怪的名词之前,我首先简要地介绍一些基础知识。简单地讲,Mozilla 所要做的就是呈现 XML 和 HTML——如此而已。在 Mozilla 中,您习以为常的所有 Web 浏览器控件(后退按钮、URL 文本框、书签、菜单等等)以及任何内容区域,都只是一些 XUL(XML-based User Interface Language,基于 XML 的用户界面语言)或者 HTML 数据的呈现。阅读新闻、邮件、聊天记录或编辑 HTML 的 Mozilla 应用程序同样如此——全部都只是呈现 XML。Mozilla 在其默认应用程序中提供了一组 chrome(非文档部件/控件),但是该框架允许通过编写少量的 XUL XML 创建您自己的应用程序,或者扩展 Mozilla 提供的应用程序。

整 个 Mozilla 应用程序包和相关的附件(如 Firefox 和 Thunderbird),其核心就是用 XUL 编写的,XUL 是一种用于定义用户界面的 XML 语言。整个 Mozilla 项目划分成几层。最底层是 Gecko Runtime Engine,它负责在屏幕上呈现可视化元素,即 HTML 标签和相关的属性、子元素以及 URL 引用的资源。很多 Mozilla 应用程序使用 XPToolkit 作为下一层,就是这一层上支持 XUL;但是一些应用程序喜欢使用 Mac OS X 上的 Camino 浏览器代替本地部件,作为 Gecko 引擎的界面。

当然如果没有程序逻辑,应用程序就做不了多少工作。只需要使用 JavaScript 处理程序逻辑,就可以编写完整的 Mozilla 应用程序——每个 XUL 控件激活一些配置好的 JavaScript 函数,可能还需要根据那个控件传递参数。(像文本字段、选择列表或者滚动条这样的控件还用于选择特定的值,而不仅仅是触发单个动作。)但是对于更高级的应 用程序,跨平台组件对象模块( Cross Platform Component Object Module,XPCOM)接口提供了一种方式,让 XUL 配置的界面调用其他编程语言编写的组件——主要是使用 C++ 编写的组件,但是其他编程语言如 Python 也提供了 XPCOM 绑定。XPCOM 类似于 Windows 中的 COM,或者 CORBA。

现在我已经描述了开发 Mozilla 界面的总体框架(XUL 调用 JavaScript,JavaScript 可以通过 XPCOM 调用 C++ 组件),本文后面将专门讨论这一庞杂体系中和 XUL 有关的那一部分,毕竟这是一个关于 XML 的专栏。例子中调用的 JavaScript alert() 函数没有多少意义,调用自定义功能的实用应用程序可以代之以其他函数。

一个小小的应用程序

为了让您领略 XUL 代码,我编写了一个定制的 Mozilla 应用程序 SimpleApp ,它包括一个 XUL 文件 SimpleApp.xul 和一个外部 JavaScript 文件 SimpleApp.js 。这个应用程序仅仅在屏幕上显示几个菜单和工具栏按钮,剩下的空间显示 HTML 文档。 SimpleApp 中配置的大部分动作仅仅是弹出一些警告框,但也有一个工具栏按钮允许选择要显示的 HTML 文档 URL。在 HTML 区域中可以像在普通浏览器中那样导航:单击链接、填写表单以及完成其他操作。

首先,看一看如何选择 HTML URL:


图 1. 在 SimpleApp 中选择 URL
在 SimpleApp 中选择 URL

SimpleApp 使用了几种不同类型的菜单。对于实际的应用程序这可能并非最好的设计,但是我想同时说明如何使用由 <menubar> 标签创建的本地菜单,以及用 <menulist> 标签创建的 XUL 菜单。后一种菜单可以出现在应用程序中的任何位置,包含在嵌套区域中,或者作为弹出菜单附加到可视化内容上。但是,XUL 也允许使用 <menupopup> 创建系统风格的弹出菜单,本例中没有说明这种菜单(系统风格的菜单通过右击鼠标或者按住 Shift 键单击鼠标来激活,通常 <menulist> 附加在框架中显示的文本上。

图 2 说明如何从本地 Mac OS X 菜单激活警告框:


图 2. SimpleApp 中的本地菜单
SimpleApp 中的本地菜单

FooBar 就像是带有子项的普通下拉菜单,尽管在截屏图像中没有显示出来。





回页首


观察 XUL

现在来看一看组成 SimpleApp 的 XUL。像多数应用程序一样,它的根元素是 <window> 。但是,仅用于增强已有应用程序如 Mozilla 浏览器功能的实用程序,根元素应该是 <overlay> 。一个应用程序可以包含多个覆盖图。

我把这个 XUL 文件分解成几部分,每一部分都有明确的功能。如果需要可以把各部分合并起来。


清单 1. SimpleApp.xul 头和脚本
												
														
<?xml version="1.0"?>
<?xml-stylesheet href="chrome://global/skin/xul.css" type="text/css"?>
<!DOCTYPE window>
<window xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
xmlns:html="http://www.w3.org/1999/xhtml"
width="600" height="280"
title="SimpleApp">
<script src="SimpleApp.js" />
<script type="application/x-javascript">
<![CDATA[ function say(txt) { alert(txt); } ]]>
</script>
<script type="application/x-javascript">
<![CDATA[
function newcontent(url) {
frames['content'].location.href=url; } ]]>
</script>

外部文件 SimpleApp.js 仅仅定义了一个简单的 JavaScript 函数 eye() ,它被那个带有眼睛图标的工具栏按钮激活。在实际的应用程序中,很可能要把必要的 JavaScript 函数库放在这类外部文件中。我还在 XUL 文件的正文部分定义了两个简单的 JavaScript 函数。


清单 2. SimpleApp.xul 系统菜单配置
												
														
<menubar id="main-menu">
<menu label="File">
<menupopup>
<menuitem label="Hello" oncommand="say('Hello world!');"/>
</menupopup>
</menu>
</menubar>

在清单 2 中, SimpleApp 定义的 File 菜单包含一个子菜单项 Hello图 2显示了激活该菜单时的情景。

现在看一看窗口内容是如何安排的:


清单 3. SimpleApp.xul 布局框和菜单列表
												
														
<vbox>
<hbox>
<menulist><label>Foo</label>
<menupopup>
<menuitem label="New SimpleApp"
oncommand="window.open('SimpleApp.xul','','chrome');"/>
<menuitem label="Something Else"
oncommand="window.open('test3.xul','','chrome');"/>
</menupopup>
</menulist>
<menulist><label>Bar</label>
<menupopup oncommand="alert('Menu item invoked.')">
<menuitem label="Item One"/>
<menuitem label="Item Two"/>
<menuitem label="Item Three"/>
</menupopup>
</menulist>
</hbox>

控制 XUL 空间几何形状很有用的一种办法是将其放在以下几种不同的框中:

  • <vbox><hbox> (常常一起使用)
  • <scrollbox>
  • <groupbox>

这里没有说明 <grid> 元素的用法,它也可以取得类似的效果。 <vbox> 总是把其中的内容布置在垂直的框中(框本身是不可见的),类似地, <hbox> 元素把内容布置在水平的框中。如果需要,可以增加 heightwidth 属性明确规定这些容器的大小,也可以使用 flexautosizeequalsize 在其他元素中(比如其他框)安排框的布局。

具体而言, SimpleApp 中的控件都放在一个控制用的 <vbox> 中,其中一个子框 <hbox> 用于 FooBar 菜单,另一个 <hbox> 放置工具栏:


清单 4. SimpleApp.xul 布局框和工具栏
												
														
<hbox>
<toolbarbutton type="button"
oncommand="alert('Button invoked.');">
<image src="http://gnosis.cx/publish/images/doc.gif" />
</toolbarbutton>
<toolbarbutton type="menu">
<image src="http://gnosis.cx/publish/images/note.gif" />
<menupopup>
<menuitem label="IBM"
oncommand="newcontent('http://ibm.com/');"/>
<menuitem label="Google"
oncommand="newcontent('http://google.com/');"/>
<menuitem label="TPiP"
oncommand="newcontent('http://gnosis.cx/TPiP/');"/>
</menupopup>
</toolbarbutton>
<toolbarbutton type="menu-button" onclick="eye();">
<image src="http://gnosis.cx/publish/images/eye.gif"/>
</toolbarbutton>
</hbox>
</vbox>

工具栏代码很有意思,Mozilla XUL 支持现代风格的工具栏,既有直接激活的按钮,也有包含下拉子菜单的按钮。贴有 note.gif 图标的按钮就是一个下拉菜单风格的按钮,如 图 1中所示。还要注意,工具栏中实际的图像是从远程 URL 中拉回来的。这个非常简单的例子是一个完全网络化的应用程序——作为一个整体结合了整个 Web 上的资源(虽然这个例子非常简单)。

谜团中的最后一部分是显示的 HTML 内容。为此,需要在 html 名称空间中创建一个 <iframe>


清单 5. SimpleApp.xul HTML 内容
												
														
<html:iframe id="content-frame" name="content"
src="http://gnosis.cx/TPiP/" flex="100%"/>
</window>

SimpleApp 的布局比较合理,基本上类似于普通的浏览器。您还可以堆砌上更多的资源,得到更加华丽、更加复杂的布局。比如,在实验 XUL 的时候我创建了一个测试案例,其中包含大小古怪的按钮和各种不同的远程 HTML 页面。它揭示了更多的布局特性,不妨把它拷贝到您的系统中:


清单 6. 华丽的 XUL 试验品(test.xul)
												
														
<?xml version="1.0"?>
<grid xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<columns>
<column/>
<column/>
</columns>
<rows flex="1">
<row>
<image src="http://www.mozilla.org/images/mozilla-banner.gif"/>
</row>
<row flex="1">
<spacer width="10"/>
<vbox align="center">
<spacer height="10"/>
<description style="border:0px; width: 120px">
This text can be <html:b> bold </html:b> and can wrap to
several lines. If I add a few more words, I can get it to
fill its column. This is a weird interface, eh?
</description>
<spacer height="10"/>
<button accesskey="A" label="A"
image="http://gnosis.cx/TPiP/hugo.gif"
oncommand="alert('Button A pressed!');"/>
</vbox>
<spacer width="10"/>
<iframe flex="1" src="http://google.com"/>
</row>
<row flex="1">
<iframe flex="1" src="http://ibm.com/" />
<button accesskey="B" flex="1" label="Button B"
oncommand="alert('Button B pressed!');"/>
<button accesskey="C" flex="1" label="Button C"
oncommand="alert('Button C pressed!');"/>
</row>
</rows>
</grid>





回页首


其他部件

这个示例应用程序只使用了少量的 XUL 控件。关于各种 XUL 元素的完备文档请参阅“XUL Programmer's Reference Manual”,在线书籍“ Creating XPCOM Components”也是非常不错的参考资料,详细介绍了 XUL 和 XPCOM 库编程。

我们再简单地介绍几种 XUL 元素。网格和框多用于简单的布局,而 deck、stack 和 bulletin board 可以提供更多的控制。后面的 <bulletinboard> 可以精确定位,而不是自动浮动控件以适应容器。

除了上述菜单之外,XUL 中还包括基本的 UI 元素,如单选框、检查框和各种不同的按钮。一些更高级的用户界面控件还有树状图、弹出窗口、编辑组件和选项卡,以及进度的显示和带有不同滚动条的大型容器的操作。

多数情况下,所有这些元素都按照其用途命名。但是在 XUL 应用程序中可以包括喜欢的任何 HTML 部件。只需要将其放在 html 名称空间中并添加上,就像您在设计 DHTML 网页时所做的那样。

清单 6 中,我悄悄地引入了一种还没有提到过的非常有用的导航元素。那些按钮有一个属性 accesskey ,可以使用键盘或者点击鼠标激活它们的动作。同样,也可以规定您认为什么样的键盘导航最适合您的应用程序。虽然默认情况下,可以使用制表键和箭头键选择菜单项,但是快捷键可以简化很多动作。





回页首


结束语

在 浏览器中开发完整的应用程序似乎很奇怪,但是现在 Mozilla 还不仅如此——它是一整套组件和 GUI 体系结构。事实上,Mozilla 和其他您所能够想到的任何 GUI 库相比,可能更富有跨平台的特色,也更广泛地安装在用户系统上。您所认为的通用 GUI/部件库——Qt、wxWindows、GTK、FOX、MFC、.NET、Carbon 等等——各有不同的优缺点。但其中没有一个可以认为已经跨用户系统安装。很多只能在 Mozilla 所支持平台中的一部分上使用,而且多数安装比较困难还存在许可的问题。仅仅因为它是一个非凡的浏览器就值得安装 Mozilla;一旦拥有它,您就有了一个定制应用程序的 自由的平台。

要使您的 Mozilla/XUL 应用程序完全跨平台,必须用 XUL 配置 GUI,并用 JavaScript 编写程序逻辑。这并不是讨论 JavaScript 优劣的地方,但显然有很多程序员更喜欢用其他语言开发,如 C++、Python 和 Perl。您 可以这 样做,但是需要使用 XPCOM 绑定到外部库,而这样会降低可移植性,或者至少增加了移植的难度。对于 Python 和 Perl 这样的脚本语言,您可以利用通用的绑定/包装程序,编写非常通用的代码(但是仍然需要适应平台的 XPCOM,如PyXPCOM)。但是对于 C++,您需要对希望支持的每种平台编译特定版本的库,要做的工作更多一些。对于简单的应用程序 JavaScript 仍然是最好的选择,特别是如果应用程序很大程度上基于 Mozilla 框架中内在的网络功能。





回页首


参考资料

  • 您可以参阅本文在 developerWorks 全球站点上的 英文原文.

  • 阅读 David 上一篇专栏文章,“ XML 问题:GUI 和 XML 配置数据”( developerWorks,2004 年 4 月),该文考察了 XML 在 Mac OS X 的 Aqua GUI 和 K Desktop Environment(KDE)中的应用。

  • 请访问 Mozilla Googlebar 项目,用于定制 XUL 增强浏览器功能的一个很棒的应用程序/覆盖图。它为每个浏览器窗口可选工具栏中增加了多种定制的搜索部件,并改进了上下文弹出菜单。

  • 试一试 Mozilla Calendar, 者是一个用 XUL 编写的成熟的应用程序,包括一些 JavaScript 代码,并通过 XPCOM 调用 C++ 库。这个日程表和它的名称一样,就是一个管理约定、联系、事件和类似东西的应用程序。Mozilla Calendar 类似于 Windows 中的 Outlook,或者 Mac OS X(使用了它的开放数据格式)中的 iCal.app,但是可以几乎等同地运行在任何 Mozilla 平台上。

  • XUL Programmer's Reference Manual可以获得关于所有 XUL 元素的完备文档,这是关于 XUL 的权威参考。

  • 阅读 Creating XPCOM Components。这本书的范围超出了 XUL 本身,但它是一个非常棒的、可免费获得的出版物,介绍了整个 XPCOM 体系结构,也包括 XUL。

  • developerWorksXML 专区 可以找到更多的 XML 资源。

  • developerWorksDeveloper Bookstore可以找到更中关于 XML 的书籍,包括 David Mertz 撰写的 Text Processing in Python

  • 使用最新的 IBM ®工具和中间件开发并测试您的 XML 应用程序,通过 订阅 developerWorks,您可以从 WebSphere ®、DB2 ®、Lotus ®、Rational ®和 Tivoli ®获得 IBM 软件,以及使用这些软件的 12 个月的许可证,它们都比您预想的要便宜得多。




回页首


关于作者

David Mertz

David Mertz 认为 WIMP 界面很快将真正消失。可以通过 mertz@gnosis.cx与 David 联系;在 http://gnosis.cx/publish/上详细介绍了他的生活。欢迎对过去、现在和未来的专栏文章提出意见和建议。您可以在 http://gnosis.cx/TPiP/了解 David 的新书 Text Processing in Python。

posted on 2006-03-21 23:48 Vincent.Chen 阅读(544) 评论(0)  编辑  收藏 所属分类: XML


只有注册用户登录后才能发表评论。


网站导航: