Apache Pivot WTKX入門

WTKX是用於創建Pivot應用程序的基於XML的標記語言。雖然,通常是用於定義用戶界面的結構,但是也可以用於聲明創建Java對象。

本節主要介紹WTKX和解釋如何使用WTKX創建和配置java對象集合。假定你已經熟悉掌握了Pivot和Java程序設計語言。

元素(element)

在WTKX中,一個XML元素可能表示一下其一:

  • 一個類的實例

  • 一個類實例的特性(屬性)

  • WTKX串行化處理指令

如果一個元素的標籤名稱以大寫字母開頭,被認爲是一個類實例。其它當做類實例的屬性處理,除非標籤名稱以保留名稱空間前綴"wtkx"開始。以wtkx名稱空間前綴開始的元素屬於串行化指令,在後面的章節會詳細的描述。

類實例元素(Class Instance Elements)

當WTK串行化(org.apache.pivot.wtkx.WTKXSerializer的一個實例, 後面會描述) 遇到一個元素的標籤是以大寫字母開頭時,它認爲標籤的名字是一個Java的類並創建一個該類的實例。元素名稱空間指定類名所屬的Java包。

例如,下面的WTKX展示了org.apache.pivot.wtk.Label類的一個實例,並顯示text"Hello,World"(和特性一個,屬性也是可以用於設置特性的值,在下節討論):

1 <Label text="Hello, World!"
2     xmlns="org.apache.pivot.wtk" />

注意:默認的名稱空間被定義爲 org.apache.pivot.wtk. 在Pivot開發中,這是一個非常常見的慣例,因爲WTKX經使用定義在該包的類來構造用戶界面。

更復雜的例子可能使用定義於其它包的類和使用多個名稱空間。名稱空間前綴可以使用於此目的。例如,下面的WTKX給包 org.apache.pivot.wtk.charts 分配了名稱空間前綴charts , 並且設置org.apache.pivot.wtk.charts.BarChartView 的實例爲Window的內容:

1 <Window xmlns="org.apache.pivot.wtk"
2     xmlns:charts="org.apache.pivot.wtk.charts">
3     <content>
4         <charts:BarChartView/>
5     </content>
6 </Window>

字典 vs.Bean字典(Dictionary vs. BeanDictionary)

通常情況下,WTKX文件中以大寫字母開頭的元素代表的是一個JavaBean類的實例,在WTKX系列化內部使用org.apache.pivot.beans.BeanDictionary 來封裝類的實例,並調用它的Set方法。然而如果名稱所代表的對象的類實現了接口org.apache.pivot.collections.Dictionary (比如 org.apache.pivot.collections.HashMap),就不使用JavaBean封裝,而是使用dictionary的方法直接存取。例如,下面的WTKX創建了一個 org.apache.pivot.collections.HashMap 的實例,並設置 "foo" 和"bar" 的值分別爲 "123" 和"456":

1 <HashMap foo="123" bar="456"
2     xmlns="org.apache.pivot.collections"/>

實例特性元素(Instance Property Elements)

那些標籤以小寫字母開始的元素代表了一個實例的特性。一個特性可能表示下面的其一情況:

  • 一個標準JavaBean特性的setter

  • 一個只讀的序列

  • 一個只讀的字典

  • 一個事件監聽者列表

WTKX串行化使用bean字典獲得的信息可以知道特性的類型和正確的處理元素的內容。

JavaBean特性Setters(JavaBean Property Setters)

如果一個元素表示一個JavaBean特性setter,元素的內容就會被當做值傳遞給特性的setter。例如,下面的WTKX創建了Label類的一個實例,並且設置label的text特性的值爲"Hello,World!":

1 <Label xmlns="org.apache.pivot.wtk">
2     <text>Hello, World!</text>
3 </Label>

下面展示了一個具有相同結果的實例,使用屬性設置text的特性:

1 <Label text="Hello, World!"
2     xmlns="org.apache.pivot.wtk"/>

下面的事例創建了一個ListView的實例,並且設置listData特性的值爲一個org.apache.pivot.collections.ArrayList 對象,一個具有多個 org.apache.pivot.wtk.content.ListItem 對象的類型:

01 <ListView xmlns="org.apache.pivot.wtk"
02     xmlns:collections="org.apache.pivot.collections"
03     xmlns:content="org.apache.pivot.wtk.content">
04     <listData>
05         <collections:ArrayList>
06             <content:ListItem text="A"/>
07             <content:ListItem text="B"/>
08             <content:ListItem text="C"/>
09         </collections:ArrayList>
10     </listData>
11 </ListView>

只讀序列(Read-Only Sequences)

如果特性代表的是一個只讀序列(一個bean特性的getter返回一個org.apache.pivot.collections.Sequence 對象並且沒有相應的setter方法),元素的內容被添加到序列。例如, org.apache.pivot.wtk.TabPane類的tabs特性返回 TabSequence的實例

1 <TabPane xmlns="org.apache.pivot.wtk">
2     <tabs>
3         <Label text="Foo"/>
4         <Label text="Bar"/>
5     </tabs>
6 </TabPane>

只讀字典(Read-Only Dictionaries)

一個特性屬性可能代表一個只讀字典(一個bean特性的getter方法返回一個org.apache.pivot.collections.Dictionary 實例,但是沒有相應的setter方法)。例如 org.apache.pivot.wtk.Component 的userData特性代表一個只讀字典特性:

1 <Label text="Hello, World!"
2     xmlns="org.apache.pivot.wtk">
3     <userData foo="123" bar="456"/>
4 </Label>

uaserData特性的屬性值被放入到字典,使用屬性的名字作爲鍵,屬性值爲鍵的值。

監聽者列表(Listener Lists)

最後屬性可能代表一個事件監聽者列表(org.apache.pivot.util.ListenerList的一個實例)。如果是這樣,子元素代表了適當的監聽者並被添加到監聽者列表。 在腳本一章節詳細描述。

屬性(Attributes)

WTKX的熟悉可能代表下面情況之一:

  • 一個標準的JavaBean特性的setter方法

  • 一個靜態的特性setter方法

  • 一個事件監聽者

JavaBean特性Setter方法(JavaBean Property Setters)

如果一個屬性代表一個bean特性的setter,屬性值會被當做參數傳遞給setter方法。如果屬性的類型爲strng,值按原樣傳遞;然而,如果屬性類型是其它簡單類型(boolean, char, byte, short, int, long, float, or double)或者簡單類型的封裝類型,在調用setter方法之前會被轉換爲適當的類型。例如,下面給出一個簡單的bean類:

1 package com.foo;
2 public class MyBean {
3     public String getFoo() { ... }
4     public void setFoo(String foo) { ... }
5     public int getBar() { ... }
6     public void setBar(int bar) { ... }
7 }

下面的WTKX實例化了bean,並調用foo和bar setters方法,並且傳遞string給setFoo和setBar:

1 <MyBean foo="hello" bar="123"
2     xmlns="com.foo"/>

然而,如果一個元素表示的對象的類已經實現了Dictionary接口(如HasmMap),屬性的類型就無法決定,也不會有類型轉換髮生,值簡單的按strng傳遞。

靜態特性Setters方法(Static Property Setters)

屬性可能擺式"靜態setters" (有些時候"附加特性")。附加特性就是那些只有在特定上下文才出現的特性(屬性)。當類被調用時,他們並不是類內定義的屬性,而是在其它的類定義(一般的,比如父容器或者組件)。

下面的WTKX爲TabPane 類的label特性調用了靜態setter:

1 <TabPane xmlns="org.apache.pivot.wtk">
2     <tabs>
3         <Label TabPane.label="First Tab" text="Tab 1"/>
4     <tabs>
5 </TabPane>

上面的WTKX代碼可以轉換爲下面對應的Javad代碼:

1 TabPane tabPane = new TabPane();
2 Label label = new Label();
3 label.setText("Tab 1");
4 tabPane.getTabs().add(label);
5 TabPane.setLabel(label, "First Tab");

調用TabPane.setLabel()把"name"特性和Label實例關聯在一起。tab pane隨後使用特性的值作爲出現在pane按鈕欄的按鈕的數據。TabPane同樣也爲tab的圖標定義了一個靜態setter。其它容器,包含Accordion和TablePane也定義了類似的setters。

注意:雖然在WTKX中靜態setter屬性定義在最前面,但事實上是在setter(text)特性後調用(就像Label的實例被添加到tab pane一樣)。 因爲靜態setter是將一個實例添加到其父類對象(組件)中,在實例爲創建之前,靜態setter是不能被調用的。添加一個對象到父對象時使得關聯的特性生效。相反的,從父對象刪除一個對象時,先前關聯的特性也被移除。

事件監聽者(Event Listeners)

最後,屬性可能代表一個事件監聽者。屬性值包含的腳本代碼用於在響應事件時被執行。詳細的描述在腳本一章節。

操作符解析(Resolution Operators)

WTKX的Setter屬性支持幾種操作符解析的處理能力:

  • 對象解引用 Object dereference

  • 資源解析Resource resolution

  • URL定位解析 URL resolution

對象解引用(Object Dereference)

對象解引用操作允許屬性相應的setter函數調用前使用一個先前定義的命名對象替換屬性的值。任何屬性其值以$開頭時都被認爲是對象解引用。

例如,一個table view header必須與一個TableView對象關聯。在Java,痛過使用setTableView方法實現。在WTKX,對象解引用操作被使用。下面的WTKX定義了一個ScrollPane對象,設置TableView爲組建的view,並且使用TableViewHeader作爲列頭。table view 痛過tableView屬性關聯列頭:

01 <ScrollPane xmlns="org.apache.pivot.wtk"
02     xmlns:wtkx="http://pivot.apache.org/wtkx">
03     <view>
04         <TableView wtkx:id="tableView">
05             ...
06         </TableView>
07     </view>
08     <columnHeader>
09         <TableViewHeader tableView="$tableView"/>
10     </columnHeader>
11 </ScrollPane>

注意:上面的例子使用了"wtkx"名稱空間前綴。這是一個由WTKX串行化對象解析的特別的名稱空間。如上所示,定義了元素的id,用於給類的實例分配一個名稱。除了解引用之外,該ID也可以用於在Java代碼系列化WTKX或者腳本代碼包含WTKX文件時獲得被實例化的元素的引用。I

其它特別的元素也被定義於wtkx名稱空間中,在後面的章節在詳細描述。

資源解析(Resource Resolution)

在WTKX中,爲了本地化的目的,資源的替代在加載時才被執行。當給出一個.org.apache.pivot.util.Resources實例時, WTKXSerializer 會使用指定的值替換資源的名稱. 資源名稱使用%前綴定義,如下所示:

1 <Label text="%myText"/
2     xmlns="org.apache.pivot.wtk">

與之關聯的本地資源文件可能包含如下所示的內容:

1 {   myText:"This is my text!"
2 }

顯示lable的文本是 "This is my text!".

WTKXSerializer 在後面會詳細的討論。

URL解析(URL Resolution)

屬性也可以用來指定URLs。一個值以'@'字符開始的屬性被轉換爲URL,該URL的地址相對於WTKX源文件所在的地址。例如,下面的WTKX從與WTKX文件相同的目錄加載圖像。WTKX轉換爲調用ImageView#setImage(java.net.URL)方法:

1 <ImageView image="@foo.png"
2     xmlns="org.apache.pivot.wtk"/>

如果沒有 "@" 操作符bean屬性就沒有相關的上下文可以解析資源的路徑。

包含(Includes)

<wtkx:include>標籤允許WTKX文件嵌入一個外部定義的WTKX文件爲其內容。 這個對於組織文件的多個部分是非常用於的。

下面的WTKX定義了Windows的內容包含一個外部文件content.wtkx文件:

1 <Window xmlns="org.apache.pivot.wtk"
2     xmlns:wtkx="http://pivot.apache.org/wtkx">
3     <content>
4         <wtkx:include src="content.wtkx"/>
5     </content>
6 </Window>

包含文件的內容使用一個嵌套的WTKXSerializer實例進行加載。如果給包含標籤分配一個ID,定義於該包含文件內的對象可以通過名稱調用WTKXSerializer#get獲得。例如,下面給如的WTKX,調用者可以在隨後使用"content.label"取得Label的實例:

1 <-- window.wtkx -->
2 <Window xmlns="org.apache.pivot.wtk"
3     xmlns:wtkx="http://pivot.apache.org/wtkx">
4     <content>
5         <wtkx:include wtkx:id="content" src="content.wtkx"/>
6     </content>
7 </Window>
1 <-- content.wtkx -->
2 <Label xmlns="org.apache.pivot.wtk"
3     xmlns:wtkx="http://pivot.apache.org/wtkx"
4     wtkx:id="label" text="Hello, World!"/>

Java 代碼:

1 Label label = (Label)wtkxSerializer.get("content.label");

定義(Defines

通常情況下WTKX中定義的類實例元素都期望自己有一個父標籤。然而,某些時候聲明的對象並不需要一個直接的父對象。<wtkx:define>標籤可以用於實現該目的。

例如,下面的WTKX實例化了一個 login對話框對象,通過include實現。對話框實例被分配了一個ID,可以用於在腳本或者Java代碼中定義與之相關的事件處理器:

1 <Window xmlns:wtkx="http://pivot.apache.org/wtkx"
2     xmlns="org.apache.pivot.wtk">
3     <wtkx:define>
4         <wtkx:include wtkx:id="loginDialog" src="login_dialog.wtkx"/>
5     </wtkx:define>
6     <content>
7         ...
8     </content>
9 </Window>

腳本(Scripting

 <wtkx:script>標籤允許調用者導入腳本代碼或者嵌入包含腳本代碼的WTKX文件。 任何JVM腳本語言都可以被使用。.The name of the scripting language is passed to the WTKXSerializer instance that is used to load the WTKX file. WTKXSerializer is discussed in more detail below.

例如,下面的WTKX定義了一個JavaScript代碼,並在JavaScript中定義了一個名稱爲foo的變量。該變量的值被用於展現定義在Windows content 的Label實例:

1 <Window xmlns:wtkx="http://pivot.apache.org/wtkx"
2     xmlns="org.apache.pivot.wtk">
3     <wtkx:script>
4     var foo = "Hello, World!";
5     </wtkx:script>
6     <content>
7         <Label text="$foo"/>
8     </content>
9 </Window>

腳本代碼也可以被定義於外部文件:

1 <Window xmlns:wtkx="http://pivot.apache.org/wtkx"
2     xmlns="org.apache.pivot.wtk">
3     <wtkx:script src="foo.js"/>
4     <content>
5         <Label text="$foo"/>
6     </content>
7 </Window>

任何在腳本中被聲明爲global的變量都被添加到WTKX文件名稱空間內,並且可以用於對象解引用操作和通過WTKXSerializer#get獲得對象的引用。

監聽者列表元素(Listener List Elements)

WTKX中的腳本代碼可能被用於定義事件處理器。每一個事件處理器定義於腳本會比定義於Java代碼更加方便。例如,下面給出的WTKX:

1 <PushButton xmlns="org.apache.pivot.wtk"
2     xmlns:wtkx="http://pivot.apache.org/wtkx"
3     wtkx:id="pushButton" buttonData="Click Me!"/>

Java代碼獲得PushButton的引用和關聯按鈕的press監聽者的代碼可能如下:

1 PushButton pushButton = (PushButton)wtkxSerializer.get("pushButton");
2 pushButton.getButtonPressListeners().add(new ButtonPressListener() {
3     public void buttonPressed(Button button) {
4         // Handle event
5     }
6 });

然而可以更加簡單的完成這個事情,一個相似的腳本代碼可能如下:

01 <PushButton xmlns="org.apache.pivot.wtk"
02     xmlns:wtkx="http://pivot.apache.org/wtkx"
03     buttonData="Click Me!">
04     <buttonPressListeners>
05         <wtkx:script>
06         function buttonPressed(button) {
07             // Handle event
08         }
09         </wtkx:script>
10     </buttonPressListeners>
11 </PushButton>

This version is quite a bit easier to read, and creates a much stronger association between the button and the handler. It doesn't even require the button to be given an ID.

當腳本被定義於監聽者列表元素內時,WTKXSerializer創建了一個局部範圍的本地處理器。其結果就是,任何出現在腳本塊中定義的變量和函數只有在塊內可見。

基於腳本的事件處理器沒有必要實現監聽者接口的所有方法,可以忽略掉方法,會被簡單的處理爲 no-op處理器。

事件監聽者屬性(Event Listener Attributes)

事件監聽者也可以被定義爲屬性,使用於靜態特性setter相似的語法。屬性的名稱包含事件處理器的接口和其名稱,通過·分隔。 和監聽者列表元素一樣,一個局部範圍的代碼被創建。 任何定義於處理器內的變量只有在處理器內可見。

例如,上面的按鈕press監聽者可以被定義爲一個屬性,如下:

1 <PushButton xmlns="org.apache.pivot.wtk"
2     xmlns:wtkx="http://pivot.apache.org/wtkx"
3     buttonData="Click Me!"
4     ButtonPressListener.buttonPressed="// Handle event"/>

基於屬性事件處理器主要使用於短小代碼的處理器,通常適合於只有單行代碼的處理器。長代碼的事件處理器最好是使用基於元素的監聽者列表或者使用Java代碼實現。

WTKX串行化(WTKXSerializer)

org.apache.pivot.wtkx.WTKXSerializer類主要用於加載和處理WTKX文件和關聯腳本與包含文件。實現了 org.apache.pivot.serialization.Serializer 接口,和返回了定義於WTKX文件中的對應的對象層次結構。.定義重載了 readObject()方法:

1 public Object readObject(String resourceName) { ... }
2 public Object readObject(URL location) { ... }
3 public Object readObject(InputStream inputStream) { ... }

第一個版本,在應用程序的路徑下加載WTKX文件資源。第二個版本的函數從一個URL中加載。

1 <Window xmlns="org.apache.pivot.wtk"
2     xmlns:wtkx="http://pivot.apache.org/wtkx">
3     <content>
4         <Label wtkx:id="label" text="Hello, World!"/>
5     </content>
6 <Window>

 

1 public void startup(Display display, Map<String, String> properties)
2     throws Exception {
3     WTKXSerializer wtkxSerializer = new WTKXSerializer();
4     Window window =
5         (Window)wtkxSerializer.readObject(getClass().getResource("window.wtkx"));
6     window.open(display);
7 }

訪問命名對象(Accessing Named Objects)

當WTKX文件的跟對象被加載以後,WTKXSerializer#get()方法允許調用者取得一個在WTKX中命名對象的實例readObject()方法會處理命名對象ID和對象實例之間的映射,使得調用者隨後可以引用到這些對象。

繼續上一個例子,下面的代碼取得了Lable實例,並且改變text爲 "Welcome to Pivot"!:

1 public void startup(Display display, Map<String, String> properties)
2     throws Exception {
3     WTKXSerializer wtkxSerializer = new WTKXSerializer();
4     Window window =
5         (Window)wtkxSerializer.readObject(getClass().getResource("window.wtkx"));
6     Label label = wtkxSerializer.getObjectByID("label");
7     label.setText("Welcome to Pivot!");
8     window.open(display);
9 }

WTKXSerializer 實現了Dictionary接口,所以調用者可以使用put和remove方法修改serializer's 名稱空間,在加載之前。

嵌套包含(Nested Includes)

定義於WTKX包含的對象可以通過get()方法取得。包含文件的ID定義了改包含的名傳空間,調用者可以使用點分隔的名稱空間路徑訪問嵌套對象:

1 Label label = (Label)wtkxSerializer.get("content.label")

 "content" 是包含Label實例的包含文件的ID, "label"是 label本身的ID。

WTKX綁定(WTKX Binding)

org.apache.pivot.wtkx包包含的註解可以用於簡單的映射命名對象到java程序。   @WTKX註解可以用於標記一個成員變量,會自動映射WTKX文件中的命名對象。WTKXSerializer 的bin() 方法用於執行實際的映射:

1 <Window xmlns="org.apache.pivot.wtk"
2     xmlns:wtkx="http://pivot.apache.org/wtkx">
3     <content>
4         <Label wtkx:id="label" text="Hello, World!"/>
5     </content>
6 <Window>

WTKXSerializer#bind() 被調用時,下面的代碼被自動添加:

1 @WTKX private Label label;

總結(Summary)

WTKX 提供了一系列特性用於幫助構建用戶接口。可以用於實例化對象、設置成員的值和定義邏輯腳本等。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章