Vincent.Chan‘s Blog

          常用鏈接

          統(tǒng)計

          積分與排名

          網(wǎng)站

          最新評論

          XML 問題: GUI 和 XML 配置數(shù)據(jù),第 2 部::Mozilla 項目和 XUL

          級別: 中級

          David Mertz, Browser, Gnosis Software, Inc.

          2004 年 5 月 26 日

          David 繼續(xù)關(guān)于如何在 GUI 界面配置中使用 XML 的話題。他考察了 Mozilla 基于 XML 的用戶界面語言(XUL),這種語言編寫的應(yīng)用程序完全不依賴所選擇的底層操作系統(tǒng)。初看起來這似乎有點奇怪,但很快您就會看到該 Mozilla 項目為構(gòu)建 GUI 提供了非常強(qiáng)大的工具,允許您開發(fā)范圍廣泛的用戶界面。

          在開始討論那些并非所有 讀者都熟悉的縮寫字符串和奇怪的名詞之前,我首先簡要地介紹一些基礎(chǔ)知識。簡單地講,Mozilla 所要做的就是呈現(xiàn) XML 和 HTML——如此而已。在 Mozilla 中,您習(xí)以為常的所有 Web 瀏覽器控件(后退按鈕、URL 文本框、書簽、菜單等等)以及任何內(nèi)容區(qū)域,都只是一些 XUL(XML-based User Interface Language,基于 XML 的用戶界面語言)或者 HTML 數(shù)據(jù)的呈現(xiàn)。閱讀新聞、郵件、聊天記錄或編輯 HTML 的 Mozilla 應(yīng)用程序同樣如此——全部都只是呈現(xiàn) XML。Mozilla 在其默認(rèn)應(yīng)用程序中提供了一組 chrome(非文檔部件/控件),但是該框架允許通過編寫少量的 XUL XML 創(chuàng)建您自己的應(yīng)用程序,或者擴(kuò)展 Mozilla 提供的應(yīng)用程序。

          整 個 Mozilla 應(yīng)用程序包和相關(guān)的附件(如 Firefox 和 Thunderbird),其核心就是用 XUL 編寫的,XUL 是一種用于定義用戶界面的 XML 語言。整個 Mozilla 項目劃分成幾層。最底層是 Gecko Runtime Engine,它負(fù)責(zé)在屏幕上呈現(xiàn)可視化元素,即 HTML 標(biāo)簽和相關(guān)的屬性、子元素以及 URL 引用的資源。很多 Mozilla 應(yīng)用程序使用 XPToolkit 作為下一層,就是這一層上支持 XUL;但是一些應(yīng)用程序喜歡使用 Mac OS X 上的 Camino 瀏覽器代替本地部件,作為 Gecko 引擎的界面。

          當(dāng)然如果沒有程序邏輯,應(yīng)用程序就做不了多少工作。只需要使用 JavaScript 處理程序邏輯,就可以編寫完整的 Mozilla 應(yīng)用程序——每個 XUL 控件激活一些配置好的 JavaScript 函數(shù),可能還需要根據(jù)那個控件傳遞參數(shù)。(像文本字段、選擇列表或者滾動條這樣的控件還用于選擇特定的值,而不僅僅是觸發(fā)單個動作。)但是對于更高級的應(yīng) 用程序,跨平臺組件對象模塊( Cross Platform Component Object Module,XPCOM)接口提供了一種方式,讓 XUL 配置的界面調(diào)用其他編程語言編寫的組件——主要是使用 C++ 編寫的組件,但是其他編程語言如 Python 也提供了 XPCOM 綁定。XPCOM 類似于 Windows 中的 COM,或者 CORBA。

          現(xiàn)在我已經(jīng)描述了開發(fā) Mozilla 界面的總體框架(XUL 調(diào)用 JavaScript,JavaScript 可以通過 XPCOM 調(diào)用 C++ 組件),本文后面將專門討論這一龐雜體系中和 XUL 有關(guān)的那一部分,畢竟這是一個關(guān)于 XML 的專欄。例子中調(diào)用的 JavaScript alert() 函數(shù)沒有多少意義,調(diào)用自定義功能的實用應(yīng)用程序可以代之以其他函數(shù)。

          一個小小的應(yīng)用程序

          為了讓您領(lǐng)略 XUL 代碼,我編寫了一個定制的 Mozilla 應(yīng)用程序 SimpleApp ,它包括一個 XUL 文件 SimpleApp.xul 和一個外部 JavaScript 文件 SimpleApp.js 。這個應(yīng)用程序僅僅在屏幕上顯示幾個菜單和工具欄按鈕,剩下的空間顯示 HTML 文檔。 SimpleApp 中配置的大部分動作僅僅是彈出一些警告框,但也有一個工具欄按鈕允許選擇要顯示的 HTML 文檔 URL。在 HTML 區(qū)域中可以像在普通瀏覽器中那樣導(dǎo)航:單擊鏈接、填寫表單以及完成其他操作。

          首先,看一看如何選擇 HTML URL:


          圖 1. 在 SimpleApp 中選擇 URL
          在 SimpleApp 中選擇 URL

          SimpleApp 使用了幾種不同類型的菜單。對于實際的應(yīng)用程序這可能并非最好的設(shè)計,但是我想同時說明如何使用由 <menubar> 標(biāo)簽創(chuàng)建的本地菜單,以及用 <menulist> 標(biāo)簽創(chuàng)建的 XUL 菜單。后一種菜單可以出現(xiàn)在應(yīng)用程序中的任何位置,包含在嵌套區(qū)域中,或者作為彈出菜單附加到可視化內(nèi)容上。但是,XUL 也允許使用 <menupopup> 創(chuàng)建系統(tǒng)風(fēng)格的彈出菜單,本例中沒有說明這種菜單(系統(tǒng)風(fēng)格的菜單通過右擊鼠標(biāo)或者按住 Shift 鍵單擊鼠標(biāo)來激活,通常 <menulist> 附加在框架中顯示的文本上。

          圖 2 說明如何從本地 Mac OS X 菜單激活警告框:


          圖 2. SimpleApp 中的本地菜單
          SimpleApp 中的本地菜單

          FooBar 就像是帶有子項的普通下拉菜單,盡管在截屏圖像中沒有顯示出來。





          回頁首


          觀察 XUL

          現(xiàn)在來看一看組成 SimpleApp 的 XUL。像多數(shù)應(yīng)用程序一樣,它的根元素是 <window> 。但是,僅用于增強(qiáng)已有應(yīng)用程序如 Mozilla 瀏覽器功能的實用程序,根元素應(yīng)該是 <overlay> 。一個應(yīng)用程序可以包含多個覆蓋圖。

          我把這個 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 函數(shù) eye() ,它被那個帶有眼睛圖標(biāo)的工具欄按鈕激活。在實際的應(yīng)用程序中,很可能要把必要的 JavaScript 函數(shù)庫放在這類外部文件中。我還在 XUL 文件的正文部分定義了兩個簡單的 JavaScript 函數(shù)。


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

          在清單 2 中, SimpleApp 定義的 File 菜單包含一個子菜單項 Hello圖 2顯示了激活該菜單時的情景。

          現(xiàn)在看一看窗口內(nèi)容是如何安排的:


          清單 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> 總是把其中的內(nèi)容布置在垂直的框中(框本身是不可見的),類似地, <hbox> 元素把內(nèi)容布置在水平的框中。如果需要,可以增加 heightwidth 屬性明確規(guī)定這些容器的大小,也可以使用 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 支持現(xiàn)代風(fēng)格的工具欄,既有直接激活的按鈕,也有包含下拉子菜單的按鈕。貼有 note.gif 圖標(biāo)的按鈕就是一個下拉菜單風(fēng)格的按鈕,如 圖 1中所示。還要注意,工具欄中實際的圖像是從遠(yuǎn)程 URL 中拉回來的。這個非常簡單的例子是一個完全網(wǎng)絡(luò)化的應(yīng)用程序——作為一個整體結(jié)合了整個 Web 上的資源(雖然這個例子非常簡單)。

          謎團(tuán)中的最后一部分是顯示的 HTML 內(nèi)容。為此,需要在 html 名稱空間中創(chuàng)建一個 <iframe>


          清單 5. SimpleApp.xul HTML 內(nèi)容
          												
          														
          <html:iframe id="content-frame" name="content"
          src="http://gnosis.cx/TPiP/" flex="100%"/>
          </window>

          SimpleApp 的布局比較合理,基本上類似于普通的瀏覽器。您還可以堆砌上更多的資源,得到更加華麗、更加復(fù)雜的布局。比如,在實驗 XUL 的時候我創(chuàng)建了一個測試案例,其中包含大小古怪的按鈕和各種不同的遠(yuǎn)程 HTML 頁面。它揭示了更多的布局特性,不妨把它拷貝到您的系統(tǒng)中:


          清單 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>





          回頁首


          其他部件

          這個示例應(yīng)用程序只使用了少量的 XUL 控件。關(guān)于各種 XUL 元素的完備文檔請參閱“XUL Programmer's Reference Manual”,在線書籍“ Creating XPCOM Components”也是非常不錯的參考資料,詳細(xì)介紹了 XUL 和 XPCOM 庫編程。

          我們再簡單地介紹幾種 XUL 元素。網(wǎng)格和框多用于簡單的布局,而 deck、stack 和 bulletin board 可以提供更多的控制。后面的 <bulletinboard> 可以精確定位,而不是自動浮動控件以適應(yīng)容器。

          除了上述菜單之外,XUL 中還包括基本的 UI 元素,如單選框、檢查框和各種不同的按鈕。一些更高級的用戶界面控件還有樹狀圖、彈出窗口、編輯組件和選項卡,以及進(jìn)度的顯示和帶有不同滾動條的大型容器的操作。

          多數(shù)情況下,所有這些元素都按照其用途命名。但是在 XUL 應(yīng)用程序中可以包括喜歡的任何 HTML 部件。只需要將其放在 html 名稱空間中并添加上,就像您在設(shè)計 DHTML 網(wǎng)頁時所做的那樣。

          清單 6 中,我悄悄地引入了一種還沒有提到過的非常有用的導(dǎo)航元素。那些按鈕有一個屬性 accesskey ,可以使用鍵盤或者點擊鼠標(biāo)激活它們的動作。同樣,也可以規(guī)定您認(rèn)為什么樣的鍵盤導(dǎo)航最適合您的應(yīng)用程序。雖然默認(rèn)情況下,可以使用制表鍵和箭頭鍵選擇菜單項,但是快捷鍵可以簡化很多動作。





          回頁首


          結(jié)束語

          在 瀏覽器中開發(fā)完整的應(yīng)用程序似乎很奇怪,但是現(xiàn)在 Mozilla 還不僅如此——它是一整套組件和 GUI 體系結(jié)構(gòu)。事實上,Mozilla 和其他您所能夠想到的任何 GUI 庫相比,可能更富有跨平臺的特色,也更廣泛地安裝在用戶系統(tǒng)上。您所認(rèn)為的通用 GUI/部件庫——Qt、wxWindows、GTK、FOX、MFC、.NET、Carbon 等等——各有不同的優(yōu)缺點。但其中沒有一個可以認(rèn)為已經(jīng)跨用戶系統(tǒng)安裝。很多只能在 Mozilla 所支持平臺中的一部分上使用,而且多數(shù)安裝比較困難還存在許可的問題。僅僅因為它是一個非凡的瀏覽器就值得安裝 Mozilla;一旦擁有它,您就有了一個定制應(yīng)用程序的 自由的平臺。

          要使您的 Mozilla/XUL 應(yīng)用程序完全跨平臺,必須用 XUL 配置 GUI,并用 JavaScript 編寫程序邏輯。這并不是討論 JavaScript 優(yōu)劣的地方,但顯然有很多程序員更喜歡用其他語言開發(fā),如 C++、Python 和 Perl。您 可以這 樣做,但是需要使用 XPCOM 綁定到外部庫,而這樣會降低可移植性,或者至少增加了移植的難度。對于 Python 和 Perl 這樣的腳本語言,您可以利用通用的綁定/包裝程序,編寫非常通用的代碼(但是仍然需要適應(yīng)平臺的 XPCOM,如PyXPCOM)。但是對于 C++,您需要對希望支持的每種平臺編譯特定版本的庫,要做的工作更多一些。對于簡單的應(yīng)用程序 JavaScript 仍然是最好的選擇,特別是如果應(yīng)用程序很大程度上基于 Mozilla 框架中內(nèi)在的網(wǎng)絡(luò)功能。





          回頁首


          參考資料

          • 您可以參閱本文在 developerWorks 全球站點上的 英文原文.

          • 閱讀 David 上一篇專欄文章,“ XML 問題:GUI 和 XML 配置數(shù)據(jù)”( developerWorks,2004 年 4 月),該文考察了 XML 在 Mac OS X 的 Aqua GUI 和 K Desktop Environment(KDE)中的應(yīng)用。

          • 請訪問 Mozilla Googlebar 項目,用于定制 XUL 增強(qiáng)瀏覽器功能的一個很棒的應(yīng)用程序/覆蓋圖。它為每個瀏覽器窗口可選工具欄中增加了多種定制的搜索部件,并改進(jìn)了上下文彈出菜單。

          • 試一試 Mozilla Calendar, 者是一個用 XUL 編寫的成熟的應(yīng)用程序,包括一些 JavaScript 代碼,并通過 XPCOM 調(diào)用 C++ 庫。這個日程表和它的名稱一樣,就是一個管理約定、聯(lián)系、事件和類似東西的應(yīng)用程序。Mozilla Calendar 類似于 Windows 中的 Outlook,或者 Mac OS X(使用了它的開放數(shù)據(jù)格式)中的 iCal.app,但是可以幾乎等同地運(yùn)行在任何 Mozilla 平臺上。

          • XUL Programmer's Reference Manual可以獲得關(guān)于所有 XUL 元素的完備文檔,這是關(guān)于 XUL 的權(quán)威參考。

          • 閱讀 Creating XPCOM Components。這本書的范圍超出了 XUL 本身,但它是一個非常棒的、可免費(fèi)獲得的出版物,介紹了整個 XPCOM 體系結(jié)構(gòu),也包括 XUL。

          • developerWorksXML 專區(qū) 可以找到更多的 XML 資源。

          • developerWorksDeveloper Bookstore可以找到更中關(guān)于 XML 的書籍,包括 David Mertz 撰寫的 Text Processing in Python

          • 使用最新的 IBM ?工具和中間件開發(fā)并測試您的 XML 應(yīng)用程序,通過 訂閱 developerWorks,您可以從 WebSphere ?、DB2 ?、Lotus ?、Rational ?和 Tivoli ?獲得 IBM 軟件,以及使用這些軟件的 12 個月的許可證,它們都比您預(yù)想的要便宜得多。




          回頁首


          關(guān)于作者

          David Mertz

          David Mertz 認(rèn)為 WIMP 界面很快將真正消失。可以通過 mertz@gnosis.cx與 David 聯(lián)系;在 http://gnosis.cx/publish/上詳細(xì)介紹了他的生活。歡迎對過去、現(xiàn)在和未來的專欄文章提出意見和建議。您可以在 http://gnosis.cx/TPiP/了解 David 的新書 Text Processing in Python。

          posted on 2006-03-21 23:48 Vincent.Chen 閱讀(611) 評論(0)  編輯  收藏 所屬分類: XML

          主站蜘蛛池模板: 乐陵市| 江川县| 博客| 紫阳县| 新宾| 凤冈县| 健康| 漯河市| 徐水县| 宜丰县| 伽师县| 信阳市| 同德县| 威海市| 阳西县| 呈贡县| 剑阁县| 宜昌市| 公安县| 河南省| 孙吴县| 赤峰市| 门头沟区| 泾阳县| 微山县| 安达市| 淳化县| 彭泽县| 育儿| 封丘县| 海宁市| 滦南县| 镇雄县| 霍邱县| 正宁县| 融水| 海城市| 武夷山市| 隆德县| 沙洋县| 湘潭县|