官术网_书友最值得收藏!

3.3.3 實用示例

在本節中,我們將要介紹一個實用的示例程序,用來說明在實際環境中XML的用法。請回憶一下卷Ⅰ第12章,GridBagLayout是Swing構件中最有用的布局管理器。然而,人們都很畏懼它,這不僅是因為它的復雜性,還因為其編碼冗長乏味。把布局描述放到一個文本文件中來替代大量重復代碼將會帶來很大便利。在本節中,你將看到怎樣用XML來描述網格組(grid bag)布局和怎樣解析布局文件。

網格組是由行和列構成的,它和HTML表格非常相似。與HTML表格相似的是,我們把它描述成一個行的序列,每個行都包含若干單元格:

gridbag.dtd指定了以下規則:

有些單元格可以跨多行多列。在網格組布局中,這是通過將gridwidth和gridheight設置為大于1的值來實現的。我們將使用相同的名字作為屬性名:

同樣,我們將屬性應用于網格組的其他約束:fill、anchor、gridx、gridy、weightx、weighty、ipadx和ipady。(我們不處理insets約束,因為它的值不是簡單類型,但是要支持它也是很簡單的。)例如:

對大多數屬性,我們都提供了與為GridBagConstraints的無參構造器所提供的默認值相同的默認值:

gridx和gridy的值受到了特殊處理,因為如果手工設定會很冗長且易于出錯。因此,提供它們的值是一項可選操作:

如果沒有提供這些值,程序會通過如下的啟發式方法來確定它們:在第0列,gridx的默認值是0;否則,它是前面的gridx加上前面的gridwidth;gridy的默認值總是與行數相同。這樣,在大多數跨越多行的情況下,你都不必指定gridx和gridy的值。但是,如果一個構件跨越多列,那么每當要跨過這個構件時,就必須指定gridx。

注意:網格組專家可能會奇怪,我們為什么不使用RELATIVE和REMAINDER機制讓網格組布局自動確定gridx和gridy的位置呢?我們試過這種方法,但是怎么也不能產生圖3-4中那個字體對話框示例的布局。閱讀了GridBagLayout的源代碼后,我們發現,很明顯,它的算法沒有完成恢復絕對位置所必需的繁重任務。

圖3-4 由XML布局定義的字體對話框

這個程序對屬性進行解析,并且設置了網格組的約束條件。例如,要讀取網格寬度,程序只需包含下面這行語句:

程序不必擔心屬性的缺失,因為當文檔中沒有指定任何其他的值時,解析器會自動提供其默認值。

如果要測試是否指定了gridx或gridy屬性,我們可以調用getAttribute方法來檢查它是否返回空串:

我們發現允許單元格包含任意對象會顯得很方便,這使我們能夠指定如邊界那樣的非構件類型。我們只要求這些對象屬于這樣的類:它具有一個默認構造器,而對每個屬性都提供了相應的獲取器(getter)/設置器(setter)對。(例如被稱為JavaBean的類。)

bean是由一個類名和0或多個屬性定義的:

屬性包含一個名字和一個值。

該值可以是整數、布爾值、字符串或者其他bean:

下面是一個典型示例,這是一個JLabel對象的實例,它的文本屬性被設為"Face:"。

把字符串用<string>標簽圍起來似乎有點麻煩。為什么不只用#PCDATA表示字符串而只留下用于其他類型的標簽呢?因為那樣我們就需要使用混合式內容,并且會把value元素的規則弱化為:

這樣的規則允許由任意文本和標簽構成的混合內容。

程序可以使用BeanInfo類來設置屬性,而BeanInfo可以枚舉bean的屬性描述符。我們用匹配名字的方式來查找屬性,然后調用它的setter方法來設置其值。

當我們的程序讀入一個用戶界面描述時,它有足夠的信息來構建和布局用戶界面構件。但是,當然,這個界面是死的,因為它沒有事件監聽器。如果要添加事件監聽器,我們必須先定位構件。因為這個緣故,我們為每個bean提供了ID類型的可選屬性:

例如,下面是一個帶有ID的組合框:

請回想一下,我們說過解析器會檢查ID是否唯一。

程序員可以用下面的方式來添加事件處理器:

注意:在這個示例中,我們只使用了XML來描述構件布局,而把在Java代碼中添加事件處理器的工作留給了程序員。你可以更進一步,將該代碼添加到XML描述中去。最有前途的方式是用JavaScript這樣的腳本語言來編碼這種代碼。如果你想添加這樣的增強功能,請參考第8章描述的Nashorn JavaScript解釋器。

程序清單3-2的程序顯示了如何使用GridBagPane類來完成設定網格組布局時所有的無聊工作,這個布局是在程序清單3-4中定義的。圖3-4顯示了運行結果。該程序只初始化了組合框(這項工作對于GridBagPane支持的bean屬性設定機制來說過于復雜了)和添加事件監聽器;程序清單3-3中的GridBagPane類用于解析XML文件,構造構件并放置它們;程序清單3-5顯示的是DTD文件。

如果選擇了包含字符串-Schema的文件,那么該程序除了DTD,還可以處理Schema。

程序清單3-6就包含了這樣的Schema。

這個例子是XML的典型用法。XML格式十分健壯,足以表達復雜的關系。在此基礎上,通過接管有效性檢查和提供默認值等例行工作,XML解析器添加了新的價值。

程序清單3-2 read/GridBagTest.java

程序清單3-3 read/GridBagPane.java

程序清單3-4 read/fontdialog.xml

程序清單3-5 read/gridbag.dtd

程序清單3-6 read/gridbag.xsd

主站蜘蛛池模板: 凤凰县| 海南省| 霍山县| 遂平县| 曲麻莱县| 紫金县| 页游| 厦门市| 湖口县| 麻江县| 吉木萨尔县| 长垣县| 越西县| 岑溪市| 枝江市| 咸宁市| 青州市| 来安县| 宣化县| 调兵山市| 岱山县| 安达市| 顺平县| 宁武县| 托克逊县| 合阳县| 天镇县| 咸丰县| 和林格尔县| 方山县| 信宜市| 和平区| 平邑县| 务川| 瑞昌市| 辛集市| 吉林省| 南乐县| 庐江县| 马鞍山市| 林州市|