PDF:

Tạo một ngôn ngữ mô tả UI XML
Xây dựng UI (giao diện người dùng) và khung làm việc đi kèm trong
ngôn ngữ Java
Arron Ferguson ([email protected])
Giảng viên
British Columbia Institute of Technology
18 12 2009
Việc viết ra các GUI (giao diện người dùng đồ hoạ) bằng mã chương trình có thể thường dẫn đến
các lựa chọn thiết kế lộn xộn, đến lượt nó lại trở nên mờ nhạt giữa các logic nghiệp vụ (business
logic) và mã UI. Hãy khám phá cách tạo một bộ thẻ UI XML khai báo với một khung làm việc
Java™ đi kèm mà phân tích cú pháp, xác thực, xây dựng, và cuối cùng là liên kết các thành
phần GUI được mô tả đến các quy tắc nghiệp vụ vào lúc chạy.
Giới thiệu
Sự phát triển GUI có thể là một công việc mệt mỏi. Các khung làm việc GUI không phải lúc nào
cũng được giải thích rõ bằng văn bản, và khối lượng mã yêu cầu có thể phát triển nhanh chóng,
làm giảm tốc độ luồng phát triển. Trên tất cả, các công cụ kéo và thả và các IDE hỗ trợ các khung
làm việc GUI này thường có thể hướng nhà phát triển phần mềm GUI về tạo bộ mã không thể quản
lý và không thể đọc được. Việc này có thể làm mờ nhạt thêm đường phân cách giữa các quy tắc
nghiệp vụ và bộ mã mô tả GUI mà có thể làm cho việc bảo trì của phần mềm đó thêm khó khăn.
Các từ chữ viết tắt (acronyms) thường sử dụng
•
•
•
•
•
•
•
•
•
•
•
API: Application programming interface - Giao diện Lập trình Ứng dụng.
DOM: Document Object Model - Mô hình Đối tượng Tài liệu.
GUI: Graphical user interface - Giao diện Người dùng Đồ họa.
HTML: Hypertext Markup Language - Ngôn ngữ Đánh dấu Siêu văn bản.
IDE: Integrated Development Environment - Môi trường Phát triển Tích hợp.
JAR: Java Archive - Định dạng tệp nén của Java.
UI: User interface - Giao diện Người dùng
URI: Uniform Resource Identifier - Bộ định danh Tài nguyên Thống nhất.
XML: Extensible Markup Language - Ngôn ngữ Đánh dấu Mở rộng.
XSD: XML Schema Infoset Model - Mô hình Infoset lược đồ XML.
W3C: World Wide Web Consortium - Tổ hợp World Wide Web,
Đây là nơi ngôn ngữ UI mô tả trở nên tiện lợi. Một UI ngôn ngữ mô tả “cái gì,” không phải là “ra
sao”. Thí dụ, HTML mô tả nội dung hiển thị, không trả về các chức năng dùng để trả về nội dung.
© Copyright IBM Corporation 2009
Tạo một ngôn ngữ mô tả UI XML
Nhẫn hiệu đăng ký
Trang 1 của 23
developerWorks®
ibm.com/developerWorks/vn/
Bằng cách không quy định “ra sao” trong các ngôn ngữ mô tả, luồng điều khiển cũng được loại ra.
Mặc dù sự mất mát này nghe có vẻ như là một sự hạn chế, nó trở thành một sức mạnh, như một tác
dụng phụ — chẳng hạn như sửa đổi toàn bộ trạng thái (thí dụ các biến) hoặc gọi ra các hàm hoặc
phương thức khác — được loại bỏ. Việc chọn ra một ngôn ngữ mô tả cũng đưa ra lợi ích của việc
tách riêng mã UI khỏi mã ứng dụng. Việc tách riêng này có thể đem lại các lợi ích tương lai chẳng
hạn như phân biệt rõ ràng giữa vai trò dự án và vai trò tổ nhóm mà thậm chí có thể giảm bớt chi
phí tích hợp các quy tắc nghiệp vụ với nhiều khung nhìn hoặc công nghệ khung nhìn.
Ngày nay, có khá nhiều mẫu UI XML mô tả đang sử dụng. Các hệ điều hành. Linux® và UNIX® sử
dụng môi trường máy tính bàn GNOME có Glade. Những người dùng Microsoft® Windows® có
Ngôn ngữ Đánh dấu Ứng dụng Mở rộng được (XAML), hỗ trợ tập hợp nhiều đặc tính, gồm việc lồng
vào mã trong XML. Định dạng MXML của Adobe® Flex® Framework mô tả các GUI cho trình chơi
nhạc Adobe Shockwave (SWF) và cả việc lồng vào mã. Xem mục Tài nguyên để có các liên kết
đến nhiều thông tin hơn.
Một tập hợp các yêu cầu cho một khung làm việc UI mô tả cơ sở trong công nghệ Java có thể là:
• Xác thực (Validation): Sử dụng lược đồ XML.
• A DOM: Một DOM thông lệ để xử lý các đặc điểm riêng chẳng hạn như duy trì sự đồng bộ
trạng thái thành phần GUI và trạng thái nút XML.
• Persistence: Sắp xếp theo thứ tự (Marshalling) và sắp xếp không theo thứ tự (unmarshalling)
của GUI.
• Image data: Lưu lại như dữ liệu Base64.
• Swing components: Việc trình bày các thành phần Swing thường được sử dụng nhiều hơn để
phát triển GUI.
Với các yêu cầu này trong đầu, bây giờ là lúc tạo XML mô tả.
XML mô tả
Một cố gắng đầu tiên ở định dạng XML, trong Liệt kê 1, trình bày một cửa sổ đơn giản, bảng panel,
và nút. Các thuộc tính thấy trong Liệt kê 1 đại diện về cơ bản cho các đặc tính được đòi hỏi, chẳng
hạn như hệ tọa độ, kích thước, và các định danh duy nhất, tham chiếu đến các thành phần trongbộ-nhớ riêng lẻ.
Liệt kê 1. Khái niệm XML mô tả
<?xml version="1.0" encoding="UTF-8"?>
<xui:XUI>
<xui:Window id="window_0" name="Hello World" width="300" height="300" x="426"
y="282" visible="true">
<xui:GridLayout height="1" width="1"></xui:GridLayout>
<xui:Panel id="panel_0" x="0" y="0" name="Hello Panel"
width="1" height="1">
<xui:GridLayout height="1" width="1"></xui:GridLayout>
<xui:Button x="0" y="0" width="1" height="1" id="button_0"
label="Press Me" enabled="true" selected="true" orientation="horizontal"/>
</xui:Panel>
</xui:Window>
<xui:Resource type="java" class="ButtonModel" uri="model.jar"/>
</xui:XUI>
Tạo một ngôn ngữ mô tả UI XML
Trang 2 của 23
ibm.com/developerWorks/vn/
developerWorks®
Lược đồ XML
UI XML mô tả này sẽ ánh xạ các phần tử XML sang khung làm việc Swing của Java, đưa ra cái lớn
nhất về tính khả chuyển, vì Swing được đảm bảo sẵn có trên tất cả các môi trường thời gian chạy
Java hiện thời. Nhiều thành phần Swing sẽ có các phần tử XML đại diện ở định dạng XML.
Khung làm việc sử dụng một lược đồ XML. Lược đồ XML cho phép áp đặt sắp xếp thứ tự xác định,
thứ bậc, và các kiểu dữ liệu trong một cá thể lược đồ. Đây là điều quan trọng; khung làm việc sẽ
chờ đợi một tập hợp các phần tử XML nào đó của các kiểu được quy định và theo một thứ tự riêng.
Liệt kê 2 trình bày các phần tử và thuộc tính ban đầu của hệ thống phân cấp trong một cá thể lược
đồ XML.
Liệt kê 2. Lược đồ UI XML mô tả: Các phần tử ban đầu
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema elementFormDefault="qualified"
targetNamespace="http://xml.bcit.ca/PurnamaProject/2003/xui"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xui="http://xml.bcit.ca/PurnamaProject/2003/xui">
<xs:element name="XUI">
<xs:complexType>
<xs:sequence>
<xs:element minOccurs="0" maxOccurs="128" ref="xui:Window"/>
<xs:element minOccurs="0" maxOccurs="1" ref="xui:Resource"/>
</xs:sequence>
<xs:attribute name="id" type="xs:anyURI" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="Resource">
<xs:complexType>
<xs:sequence>
</xs:sequence>
<xs:attribute name="uri" type="xs:anyURI" use="required"/>
<xs:attribute name="class" type="xs:token" use="required"/>
<xs:attribute name="type" use="required">
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="java"/>
<xs:enumeration value="groovy"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
<xs:element name="Window">
<xs:complexType>
<xs:sequence>
<xs:element ref="xui:GridLayout"/>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element ref="xui:BasicDialog"/>
<xs:element ref="xui:OpenFileDialog"/>
<xs:element ref="xui:SaveFileDialog"/>
<xs:element ref="xui:CustomDialog"/>
<xs:element ref="xui:Panel"/>
<xs:element ref="xui:SplitPanel"/>
<xs:element ref="xui:TabbedPanel"/>
</xs:choice>
<xs:element minOccurs="0" maxOccurs="1" ref="xui:MenuBar"/>
</xs:sequence>
Tạo một ngôn ngữ mô tả UI XML
Trang 3 của 23
developerWorks®
ibm.com/developerWorks/vn/
<xs:attribute name="id" type="xs:ID" use="required"/>
<xs:attribute name="x" type="xs:short" use="required"/>
<xs:attribute name="y" type="xs:short" use="required"/>
<xs:attribute name="width" type="xs:unsignedShort" use="required"/>
<xs:attribute name="height" type="xs:unsignedShort" use="required"/>
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="visible" type="xs:boolean" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="GridLayout">
<xs:complexType>
<xs:attribute name="width" type="xs:unsignedShort" use="required"/>
<xs:attribute name="height" type="xs:unsignedShort" use="required"/>
</xs:complexType>
</xs:element>
</xs:schema>
Hãy quan sát chi tiết lược đồ. Đầu tiên, mô tả XML phải đến trước mọi thứ — thậm chí trước cả các
khoảng trống và bình luận, như được chỉ ra theo XML Recommendation (tiến cử XML). Tiếp theo,
phần tử schema chứa các phần tử khác:
• elementFormDefault="qualified" trình bày rằng tất cả các phần tử phải có một vùng tên —
hoặc là một tiền tố hoặc một vùng tên mặc định.
• targetNamespace="http://xml.bcit.ca/PurnamaProject/2003/xui" quy định URI vùng tên
đích.
• Cá thể lược đồ sử dụng XML W3C Schema Recommendation và tất cả các phần tử trong nó
(xmlns:xs="http://www.w3.org/2001/XMLSchema").
• xmlns:xui="http://xml.bcit.ca/PurnamaProject/2003/xui" xác định một không gian tên
nữa và tiền tố đi kèm của nó.
Việc sử dụng các không gian tên trong một XSD là rất quan trọng: Nó loại bỏ xung đột về không
gian tên. Một xung đột không gian tên xảy ra khi có từ hai phần tử trở lên từ hai hay nhiều định
dạng XML có cùng một tên. Xung đột này gây ra sự nhầm lẫn cho bất kỳ ứng dụng nào quan tâm
đến bộ thẻ tương ứng của nó. Bằng cách sử dụng các không gian tên và các tiền tố không gian tên
đi kèm, bạn tránh được hoàn toàn vấn đề này.
Tiếp theo, phần tử kiểu dữ liệu mức gốc XUI nói rõ rằng:
• Cho phép một chuỗi từ 0 đến 128 các phần tử Window và cuối cùng là một phần tử Resource
Cả hai phần tử này là phần tử quy chiếu tìm thấy sau này trong cá thể lược đồ.
• Có thuộc tính id được đòi hỏi và phải thuộc kiểu anyURI.
Phần tử XUI (có thể) chứa nhiều phần tử Window mặc dù nó có thể không có các phần tử Window dựa
trên một giá trị 0 trong thuộc tính minOccurs. Đối với phần tử Resource:
• Nó có một mô hình nội dung rỗng do phần tử rỗng xs:sequence của nó xs:sequence.
• Nó có ba thuộc tính, tất cả đều được yêu cầu.
• Thuộc tính cuối cùng, thuộc tính type, tạo một kiểu đơn giản dẫn xuất từ kiểu được định nghĩa
của XSD (token), nơi mà mặt hạn chế là enumeration, có tính đến các giá trị bằng chữ được
liệt kê của java và groovy.
Tạo một ngôn ngữ mô tả UI XML
Trang 4 của 23
ibm.com/developerWorks/vn/
developerWorks®
Mục đích của phần tử Resource là cung cấp khung làm việc Java mà URI của một tài nguyên (một
JAR, trong trường hợp này) chứa các lớp Java được biên dịch mà có thể được nạp vào thời gian
chạy và được liên kết đến. Tài nguyên này dựa vào một lớp riêng (giá trị của thuộc tính class mà sẽ
được gọi ra, về bản chất đưa ra một lớp được biểu hiện ra mà sẽ trả lời tất cả các sự kiện được tạo
từ GUI.
Phần tử Window:
• Chứa một chuỗi của một GridLayout, một sự lựa chọn không hạn chế một trong số các phần
tử BasicDialog, OpenFileDialog, SaveFileDialog, CustomDialog, Panel, SplitPane, và
TabbedPane, cuối cùng là số 0 hoặc một MenuBar.
• Có bảy thuộc tính — tất cả đều được yêu cầu — sử dụng các kiểu dữ liệu được định nghĩa
khác nhau (chú ý tiền tố xs) trong ML Schema Recommendation.
có thể chứa nhiều vùng chứa khác nhau ở mức cao nhất và mức trung bình. Phần tử Window
tham chiếu đến một phần tử GridLayout. Phần tử GridLayout quy định kích thước của một lưới
các ô mà các thành phần có thể chiếm giữ. GridLayout đưa ra các đặc tính bố trí tương tự như
java.awt.GridBagLayout trong môi trường Java loại trừ mà không gặp bất kỳ sự phức tạp nào.
Window
Cho đến lúc này, rõ ràng là Lược đồ XML là có ý nghĩa đáng kể. Liệt kê 3 trình bày một vài phần tử
nữa.
Liệt kê 3. Lược đồ UI XML mô tả: nhiều phần tử hơn
...
<xs:element name="CustomDialog">
<xs:complexType>
<xs:sequence>
<xs:element ref="xui:GridLayout"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="xui:Panel"/>
</xs:sequence>
<xs:attribute name="modal" type="xs:boolean" use="required"/>
<xs:attribute name="idref" type="xs:IDREF" use="optional"/>
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="id" type="xs:ID" use="required"/>
<xs:attribute name="x" type="xs:short" use="required"/>
<xs:attribute name="y" type="xs:short" use="required"/>
<xs:attribute name="width" type="xs:unsignedShort" use="required"/>
<xs:attribute name="height" type="xs:unsignedShort" use="required"/>
<xs:attribute name="visible" type="xs:boolean" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="Panel">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="1" minOccurs="1" ref="xui:GridLayout"/>
<xs:choice minOccurs="0" maxOccurs="unbounded">
<xs:element minOccurs="0" maxOccurs="unbounded" ref="xui:Button"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="xui:Calendar"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="xui:CheckBox"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="xui:ComboBox"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="xui:HypertextPane"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="xui:Image"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="xui:Label"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="xui:List"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="xui:PasswordField"/>
Tạo một ngôn ngữ mô tả UI XML
Trang 5 của 23
developerWorks®
ibm.com/developerWorks/vn/
<xs:element minOccurs="0" maxOccurs="unbounded" ref="xui:ProgressBar"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="xui:RadioButton"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="xui:SliderBar"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="xui:Table"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="xui:TextArea"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="xui:TextField"/>
<xs:element minOccurs="0" maxOccurs="unbounded" ref="xui:Tree"/>
</xs:choice>
</xs:sequence>
<xs:attribute name="x" type="xs:unsignedShort" use="required"/>
<xs:attribute name="y" type="xs:unsignedShort" use="required"/>
<xs:attribute name="width" type="xs:unsignedShort" use="required"/>
<xs:attribute name="height" type="xs:unsignedShort" use="required"/>
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="id" type="xs:ID" use="required"/>
<xs:attribute name="idref" type="xs:IDREF" use="optional"/>
</xs:complexType>
</xs:element>
<xs:element name="RadioButton">
<xs:complexType>
<xs:sequence>
<xs:element maxOccurs="3" minOccurs="0" ref="xui:Image"/>
</xs:sequence>
<xs:attribute name="label" type="xs:string" use="required"/>
<xs:attribute name="x" type="xs:unsignedShort" use="required"/>
<xs:attribute name="y" type="xs:unsignedShort" use="required"/>
<xs:attribute name="width" type="xs:unsignedShort" use="required"/>
<xs:attribute name="height" type="xs:unsignedShort" use="required"/>
<xs:attribute name="enabled" type="xs:boolean" use="required"/>
<xs:attribute name="selected" type="xs:boolean" use="required"/>
<xs:attribute name="id" type="xs:ID" use="required"/>
<xs:attribute name="orientation" use="required">
<xs:simpleType>
<xs:restriction base="xs:token">
<xs:enumeration value="horizontal"/>
<xs:enumeration value="vertical"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:element>
...
Hãy lưu ý là thông tin trạng thái ổn định được lưu trữ — thông tin trạng thái duy nhất có thể trợ
giúp trong việc tái cấu trúc các thành phần GUI. Một thí dụ là thông tin trạng thái của phần tử
CustomDialogt:
• Số lượng các phần tử Panel cho phép trong hội thoại.
• Hội thoại theo kiểu mô thái không (Một hội thoại mô thái bẫy trọng tâm đến khi người dùng
đóng hội thoại lại.)
• Hệ tọa độ (x và y tính theo pixel) trong máy tính để bàn.
• Kích thước (chiều rộng và chiều cao tính theo pixel).
• Tầm nhìn của cửa sổ.
Một bảng Panel là một vùng chứa trung bình và cho phép một số lượng khá lớn các thành phần
nguyên tử được chứa. Xem lại Liệt kê 3, Panel có chính xác một GridLayout và một sự chọn lựa
không có thành phần nguyên tử được đặt bên trong Panel này hoặc nhiều như cần thiết. Panel
tự nó có hệ toạ độ x và y. Tuy nhiên, khác với việc tham chiếu đến các pixel trong máy tính bàn
(như CustomDialog tiến hành), Panel sử dụng hệ toạ độ x và y để tham chiếu đến việc định vị trong
Tạo một ngôn ngữ mô tả UI XML
Trang 6 của 23
ibm.com/developerWorks/vn/
developerWorks®
của vùng chứa cha. Như một con búp bê Nga, kết cấu lồng nhau này bắt chước rất
giống với nguyên tắc bố trí của Swing. Với toàn bộ cái này ở đúng chỗ, đây là lúc để nhằm đến việc
cài đặt phần mềm.
GridLayout
Hỗ trợ khung làm việc Java
Chúng ta hãy bắt đầu bằng một tổng quan về khung làm việc Java dự kiến. Bộ mã trong Liệt kê 4
trình bày các bước mà lập trình viên ứng dụng phải thực hiện theo để tạo một ứng dụng.
Liệt kê 4. Khái niệm các cuộc gọi API Java
try {
// Gain access to a XUI builder through factory
// In this framework the term XUI is going to represent the custom DOM
XUIBuilder builder = XUIBuilderFactory.getInstance().getXUIBuilder(); // (1)
// Validate and parse (unmarshal) the XML document
builder.parse("browser.xml"); // (2)
// Build a custom DOM
XUI xui = builder.getXUIDocument();
// (3)
// Create 1:1 GUI component mapping to custom DOM
xui.visualize(); // (4) (5)
// Create bindings to data model (i.e. JAR file from Resource element)
xui.bind(); // (6)
// Get root node from the XUI document
XUINode root = xui.getRoot();
// Save a copy of the DOM to file (marshal)
xui.marshalXUI("browser-marshalled.xml");
} catch (XUIParseException xpe) {
xpe.printStackTrace();
} catch (XUIBindingException xbe) {
xbe.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
Các bước trong Liệt kê 4 định nghĩa một sự tách biệt rõ ràng về chức năng và có tính đến sự tinh tế
hơn của các thành phần của khung làm việc. Một cố gắng về việc hình dung luồng này chỉ ra trong
Hình 1. Các số khoanh tròn trong Hình 1 trùng hợp với số được bình luận trong Liệt kê 4 mặc dù mã
trình bày hai bước bổ sung (lấy lại một tham chiếu đến nút gốc XUI và sự lưu tổ chức dữ liệu DOM
thành tệp). Đó là các bước:
Mô hình Đối tượng Tài liệu là gì?
Một Mô hình Đối tượng Tài liệu (viết tắt là DOM) là một việc ánh xạ của các phần tử XML
thành các đối tượng trong bộ nhớ (được một API cung cấp) như vậy cho phép các lập trình
viên đọc dữ liệu XML vào các đối tượng trong bộ nhớ (gọi là unmarshalling), thao tác dữ liệu,
và sau đó viết dữ liệu trở lại thành XML (gọi là marshalling). DOM nổi tiếng và thường sử
dụng nhất là W3C DOM.
Hình 1 minh hoạ các bước sau đây
Tạo một ngôn ngữ mô tả UI XML
Trang 7 của 23
developerWorks®
ibm.com/developerWorks/vn/
1. Một Builder được lấy ra từ một BuilderFactory.
2. Builder trước tiên đảm bảo rằng tài liệu XML đã được xác thực và được phân tích cú pháp
trước khi nó cho phép lấy một tài liệu XUI. Nếu việc phân tích cú pháp hoặc xác thực thất bại,
một XUIParseException sẽ xuất hiện và khung làm việc sẽ hủy bỏ việc nạp tài liệu.
3. Builder tạo DOM nơi các đối tượng phản ánh các phần tử XML được đọc vào.
4. Một đối tượng Realizer, được gọi ra bên trong bởi đối tượng XUI, là một thể hiện và sẵn sàng
thực hiện bước tiếp theo.
5. Sự hiểu biết rõ ở chỗ khung làm việc tạo hệ thống phân cấp các thành phần GUI dựa trên hệ
thống phân cấp của các nút XML đã tạo trước đó (lõi thực của công cụ của khung làm việc).
6. Sử dụng khả năng phản chiếu trong môi trường Java, logic mô hình (một phần của ứng dụng
điều khiển UI) được gắn với các thành phần GUI đã được nhận biết.
Hình 1. Luồng khung làm việc và khung nhìn chi tiết của các bước mà API XUI
thực hiện để xây dựng nên một GUI
Luồng gọi ra sáu bước này dễ sử dụng nhưng chứa một sự xáo trộn về các thông báo và việc
thuyết minh các đối tượng được cài đặt ẩn (under the hood), đáng được khám phá tiếp theo. Phần
trung tâm của khung làm việc là ở các bước 5 và 6.
Cấu tạo thành phần GUI & nút XML
Trong Hình 1, bước 5 tạo một mô hình thành phần. Việc này cho phép ghép đôi một nút XML (bây
giờ là một đối tượng trong bộ nhớ) với thành phần GUI. Việc ghép đôi này đòi hỏi một sự đồng bộ
hoá rất nghiêm ngặt của các sự kiện sau:
• Đối với mỗi XUINode (đối tượng trong bộ nhớ đại diện cho bất kỳ phần tử XML nào) được
khung làm việc đọc vào, một XUIComponent phải được tạo để bao quanh XUINode.
Tạo một ngôn ngữ mô tả UI XML
Trang 8 của 23
ibm.com/developerWorks/vn/
developerWorks®
• Đối với mỗi XUIComponent đã tạo trong bộ nhớ, một đồng đẳng GUI, chẳng hạn như một
javax.swing.JFrame, phải được tạo.
• Mỗi khi một cá thể XUIComponent— hoặc một trong những kiểu con của nó, chẳng hạn như một
XUIButton— được sửa đổi (thí dụ, khi kích thước được thay đổi), XUIComponent sẽ đảm bảo
rằng cả XUINode và đồng đẳng GUI sẽ được cập nhật đồng thời và tương đương.
Bằng cách đáp ứng các yêu cầu trên đây, khung làm việc cho phép lập trình viên đọc tài liệu XML
(unmarshalling), sửa đổi DOM, và lưu thay đổi vào một tài liệu XML (marshalling). Các lập trình
viên thậm chí có thể tạo các DOM mới theo chương trình và tổ chức lưu dữ liệu chúng.
Sắp xếp thứ tự nút DOM
Để cho một XUINode tự sắp xếp thứ tự dữ liệu như XML, một cài đặt tuỳ chỉnh của phương thức
toString được đưa ra (trong Liệt kê 5). Nút gốc có thể chứa nhiều nút con. Mỗi nút con có thể chứa
tập hợp các nút con của chính nó v.v… Bằng việc gọi ra phương thức toString của nút ở mức gốc,
khung làm việc có thể dễ dàng sắp xếp thứ tự toàn bộ tài liệu XML. Các vùng tên được bổ sung và
mỗi phần tử được tạo nên với thông tin về cấp độ của nó trong hệ thống phân cấp (thông qua biến
level). Với cách đó, khi phương thức toString được gọi, nó dành nơi ngoài để dễ đọc tài liệu này
theo cách thủ công.
Liệt kê 5. Cài đặt phương thức XUINode toString
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
String namespacePrefix = "";
// insert indenting ... 2 spaces for now.
if(isRoot) {
sb.append(XMLPI + "\n");
sb.append(API_COMMENT + "\n");
} else {
sb.append("\n");
for(int s = 0; s < level; s++) {
sb.append(" ");
}
}
sb.append("<");
// get namespaces for this node
Enumeration keys = nameSpaces.keys();
String names = "";
while(keys.hasMoreElements()) {
String uri = (String)keys.nextElement();
String prefix = (String)nameSpaces.get(uri);
/* if its the xsi namespace (XML Schema Instance),
* ignore it, this isn't part of that namespace but it is
* needed for the XML Schema validator to work. */
if(!(prefix.equals("xsi"))) {
sb.append(prefix + ":");
namespacePrefix = prefix;
}
names += (" " + "xmlns:" + prefix + "=\"" + uri + "\"");
}
if(beginOfNamespace) {
sb.append(name + names);
} else {
sb.append(name);
}
Tạo một ngôn ngữ mô tả UI XML
Trang 9 của 23
developerWorks®
ibm.com/developerWorks/vn/
// do attributes if there are any
if(attributes.getLength() > 0) {
int length = attributes.getLength();
for(int i = 0; i < length; i++) {
String attributeValue = attributes.getValue(i);
String attributeQName = attributes.getQName(i);
sb.append(" " + attributeQName + "=\"" + attributeValue + "\"");
}
}
sb.append(">");
sb.append(cdata);
int size = childNodes.size();
for(int i = 0; i < size; i++) {
XUINode e = (XUINode)childNodes.get(i);
sb.append(e.toString());
}
if(size > 0) {
sb.append("\n");
for(int s = 0; s < (level); s++)
sb.append(" ");
}
if(namespacePrefix.length() > 0) {
sb.append("</" + namespacePrefix + ":" + name + ">");
} else {
sb.append("</" + name + ">");
}
return sb.toString();
}
Bổ sung vào một thành phần vùng chứa
Một mục khác đáng khám phá là kiểu vùng chứa XUIWindow, kiểu con gián tiếp của XUIComponent.
Việc cài đặt XUIWindow đại diện cho một thành phần javax.swing.JFrame và do đó phải cho phép
các thành phần con sẽ được bổ sung vào sắp đặt. Liệt kê 6 trình bày việc cài đặt. Bước đầu tiên
là đảm bảo rằng chỉ các kiểu thành phần nhất định có thể được bổ sung vào XUIWindow. Nếu như
vậy thì thể hiện nút DOM của XUIComponent, một XUINode, được lấy lại để truy cập các đặc tính của
thành phần đó. Lưu ý rằng việc này đòi hỏi tất cả các hàm dựng của XUIComponent khởi tạo các giá
trị này.
Một việc kiểm tra xa hơn được thực hiện để đảm bảo rằng thành phần này là một vùng chứa trung
bình (thí dụ một XUIPanel) rằng vùng chứa trung bình vừa hợp trong lưới của các hàng và cột của
XUIWindow. Cuối cùng, thành phần đó có thể được bổ sung vào XUIWindow bằng cách đảm bảo
thành phần đó được kích hoạt, được thiết lập đúng vị trí trong lưới bố trí, và rằng XUINode (biến
win) của XUIWindow được cung cấp một tham chiếu đến XUINode của thành phần con mới— lời gọi
addChildNode().
Liệt kê 6. Cài đặt Phương thức addComponent của XUIWindow
public void addComponent(XUIComponent component) throws XUITypeFormatException {
if(component instanceof XUIBasicDialog
|| component instanceof XUIOpenFileDialog
|| component instanceof XUICustomDialog
|| component instanceof XUIMenuBar
|| component instanceof XUIPanel
|| component instanceof XUISplitPanel
|| component instanceof XUITabbedPanel
|| component instanceof XUISaveFileDialog) {
// get the node
XUINode node = component.getNodeRepresentation();
Tạo một ngôn ngữ mô tả UI XML
Trang 10 của 23
ibm.com/developerWorks/vn/
developerWorks®
if(!(component instanceof XUIMenuBar)) {
int x = Integer.parseInt(node.getAttributeValue("x"));
int y = Integer.parseInt(node.getAttributeValue("y"));
int width = Integer.parseInt(node.getAttributeValue("width"));
int height = Integer.parseInt(node.getAttributeValue("height"));
// can't add dialogs so need to check for type here.
if(component instanceof XUIBasicDialog
|| component instanceof XUIOpenFileDialog
|| component instanceof XUICustomDialog
|| component instanceof XUISaveFileDialog) ; // nothing
else {
// check to make sure it fits within the grid.
Dimension localGrid = this.getGrid();
if(width > localGrid.getWidth() || height >
localGrid.getHeight()) {
throw new XUITypeFormatException(node.getName()
+ " (id: " + node.getAttributeID()
+ ") must be within this window's grid width and"
+ "height (w: " + localGrid.getWidth()
+ " + h: " + localGrid.getHeight() + ")");
}
Rectangle rect = new Rectangle(y, x, width, height);
component.getPeer().setEnabled(true);
frame.getContentPane().add(component.getPeer(), rect);
// for mapping components to the regions they occupy
childComponentMappings.put(component, rect);
}
component.setComponentLocation(x, y);
} else {
// do specifics for a menubar
frame.setJMenuBar((JMenuBar)component.getPeer());
}
frame.invalidate();
frame.validate();
// add the component's node
int level = win.getLevel();
node.setLevel(++level);
if(win.getParent() == null)
win.addChildNode(node);
} else {
StringBuffer sb = new StringBuffer();
sb.append("Type not supported in XUIWindow. ");
sb.appen("The following types are supported:\n");
for(int i = 0; i < supportedComponents.size(); i++) {
String s = (String)supportedComponents.get(i);
sb.append("- " + s + "\n");
}
throw new XUITypeFormatException(sb.toString());
}
}
Liên kết
Một lĩnh vực cuối cùng của bộ mã đáng được kiểm tra là việc xử lý gắn với thời gian chạy. Khi
phương thức bind (liên kết) của đối tượng XUI được gọi, một cá thể của BindingFactory được gọi
ra.
Tạo một ngôn ngữ mô tả UI XML
Trang 11 của 23
developerWorks®
ibm.com/developerWorks/vn/
Phương thức doBinding của BindingFactory (trong Liệt kê 7) phải thực hiện một vài việc để gắn mã
mô hình vào GUI được kiến thiết:
• Nắm lấy URL, dù đó là cục bộ, trên Internet, hay là quan hệ.
• Quan sát kỹ JAR thông qua lớp JarURLConnection và nạp các lớp nhờ bộ nạp lớp tuỳ chỉnh và
riêng biệt.
• Tìm kiếm một lớp phù hợp với tên thuộc tính class của thành phần Resource từ tài liệu XML
được nạp. Lớp đó là điểm vào mô hình.
• Tạo một cá thể của lớp điểm vào bằng cách sử dụng khung làm việc phản chiếu Java và gọi
ra phương thức init của nó. Phương thức init về khái niệm là tương tự với phương thức main
của một lớp Java điển hình ở chỗ cả hai phương thức đều là điểm vào.
• Nếu tệp JAR chứa hình ảnh, hãy nạp chúng vào bộ nhớ.
Liệt kê 7. Phương thức doBinding của BindingFactory
public void doBinding(XUINode resource, XUI xui) throws XUIBindingException,
MalformedURLException, IOException {
if(resource.getAttributeValue("type").equals("java")) {
String className = resource.getAttributeValue("class");
String aURLString = resource.getAttributeValue("uri");
URL url = null;
// get the url ... if it's not a valid URL, then try and grab
// it as a relative URL (i.e. java.io.File). If that fails
// re-throw the exception, it's toast
try {
url = new URL("jar:" + aURLString + "!/");
} catch (MalformedURLException mue) {
String s = "jar:file://" + new File(aURLString)
.getAbsolutePath().replace("\\", "/") + "!/";
url = new URL(s);
if(url == null) {
// it really was malformed after all
throw new
MalformedURLException("Couldn't bind to: "
+ aURLString);
}
}
// get a jar connection
JarURLConnection jarConnection = (JarURLConnection)url.openConnection();
// get the jar file
JarFile jarFile = jarConnection.getJarFile();
// jar files have entries. Cycle through the entries until finding
// the class sought after.
Enumeration entries = jarFile.entries();
// the class that will be the entry point into the model
JarEntry modelClassEntry = null;
Class modelClass = null;
XUIClassLoader xuiLoader =
new XUIClassLoader(this.getClass().getClassLoader());
while(entries.hasMoreElements()) {
JarEntry remoteClass = (JarEntry)entries.nextElement();
// load the classes
if(remoteClass.getName().endsWith(".class")) {
// have to get the second last word between period marks. This
// is because the convention allows for:
// org.purnamaproject.xui.XUI
// that is, the periods can represent packages.
StringTokenizer st =
new StringTokenizer(remoteClass.getName(), ".");
String previousToken = st.nextToken();
String currentToken = "";
String nameOfClassToLoad = previousToken;
Tạo một ngôn ngữ mô tả UI XML
Trang 12 của 23
ibm.com/developerWorks/vn/
developerWorks®
while(st.hasMoreTokens()) {
currentToken = st.nextToken();
if(currentToken.equals("class"))
nameOfClassToLoad = previousToken;
else {
nameOfClassToLoad += currentToken;
}
}
// get an output stream (byte based) attach it to the
//inputstream from the jar file based on the jar entry.
ByteArrayOutputStream baos = new ByteArrayOutputStream();
InputStream is = jarFile.getInputStream(remoteClass);
final byte[] bytes = new byte[1024];
int read = 0;
while ((read = is.read(bytes)) >= 0) {
baos.write(bytes, 0, read);
}
Class c = xuiLoader.getXUIClass(nameOfClassToLoad, baos);
// check for the class that has the init method.
if(remoteClass.getName().equals(className + ".class")) {
modelClassEntry = remoteClass;
modelClass = c;
}
} else {
String imageNameLowerCase = remoteClass.getName().toLowerCase();
if(imageNameLowerCase.endsWith(".jpeg")
|| imageNameLowerCase.endsWith(".jpg")
|| imageNameLowerCase.endsWith(".gif")
|| imageNameLowerCase.endsWith(".png")) {
// add resources (images)
XUIResources.getInstance().addResource(remoteClass, jarFile);
}
}
}
// now instantiate the model.
try {
// create a new instance of this class
Object o = modelClass.newInstance();
// get the method called 'init'. This is part of the API
// requirement
Method m = modelClass.getMethod("init", new Class[] {XUI.class});
// at last, call the method up.
m.invoke(o, new Object[] {xui});
} catch(InstantiationException ie) {
ie.printStackTrace();
} catch(IllegalAccessException iae) {
iae.printStackTrace();
} catch(NoSuchMethodException nsm) {
nsm.printStackTrace();
} catch(InvocationTargetException ite) {
System.out.println(ite.getTargetException());
ite.printStackTrace();
}
} else {
throw new XUIBindingException(
"This platform/API requires Java libraries.");
}
}
Sau khi đã quan sát cơ chế của khung làm việc này, bây giờ là lúc đưa khung làm việc đi chạy thử
và trình diễn một trong các ứng dụng mẫu.
Tạo một ngôn ngữ mô tả UI XML
Trang 13 của 23
developerWorks®
ibm.com/developerWorks/vn/
Khung làm việc hoạt động
Khung làm việc dự án (xem mục Tải về) chứa một vài mẫu. Trình duyệt Web mẫu khá chi tiết ở
những gì nó thực hiện.
Tài liệu UI XML trình duyệt Web
Mẫu này đưa ra một mẫu thế giới thực hợp lý về cái mà bạn có lẽ đang chờ đợi để đặt trong một tài
liệu UI XML mô tả. Quan sát Liệt kê 8, Window chính có hệ toạ độ x và y được xác định và giá trị id.
Tất cả các phần tử phải có các giá trị mã nhận dạng duy nhất đối với các quy tắc nghiệp vụ để có
thể tham chiếu đến các thành phần này.
Phần tử Window chứa một vài phần tử con gồm:
•
•
•
•
•
•
•
Một Panel đưa ra bố trí chính.
Một OpenFileDialog để mở các trang Web mới.
Một SaveFileDialog để lưu trang Web hiện đang được xem.
Một CustomDialog hiển thị một hội thoại có thoát ra hoặc không.
Một CustomDialog hiển thị các đánh dấu Web (Web bookmarks).
Một MenuBar được hiển thị trên đầu Window và đưa ra chức năng mục trình đơn.
Một Resource để tham chiếu mã mô hình Java điều khiển UI này.
Tất cả các toạ độ của các thành phần được chứa (chẳng hạn như một Button) tham chiếu đến các
vị trí trong lưới. Tất cả các kích thước của các thành phần được chứa tham chiếu đến độ rộng và độ
lớn bao nhiêu ô mà mỗi thành phần nằm trong lưới. Các định nghĩa của thành phần là có tính mô tả
cao ở chỗ chúng định nghĩa các đặc tính chứ không phải là logic về cách các đặc tính đó đã được
sử dụng hoặc tạo. Một vài điểm thú vị nữa trong tài liệu này là:
• Các MenuItem có thể có nhanh chóng các phím nóng (quick keys), chẳng hạn như Ctrl-X để
thoát khỏi ứng dụng.
• Window có các hội thoại, nhưng, theo mặc định, các hội thoại này không nhìn thấy được đến khi
nào người dùng gọi ra.
• Tất cả các vùng chứa (thí dụ một Panel) phải có các bố trí và phải quy định số hàng và cột ở
bố trí đó.
Liệt kê 8. Trình duyệt Web UI XML
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated by The Purnama Project XUI API version 0.5 -->
<xui:XUI xmlns:xui="http://xml.bcit.ca/PurnamaProject/2003/xui"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xml.bcit.ca/PurnamaProject/2003/xui ../../xui.xsd"
id="http://xml.bcit.ca/PurnamaProject/examples/XUIWebBrowser">
<xui:Window id="window_0" name="XUI Web Browser" x="200" y="20" width="800"
height="600" visible="true">
<xui:GridLayout width="1" height="1"></xui:GridLayout>
<xui:Panel x="0" y="0" width="1" height="1" id="panel_0" name="main panel"
idref="window_0">
<xui:GridLayout width="8" height="8"></xui:GridLayout>
<xui:HypertextPane x="1" y="0" width="8" height="7" id="hyper_0"
uri="http://www.w3c.org"></xui:HypertextPane>
<xui:Button x="0" y="0" width="1" height="1" id="button_0" label="Back"
enabled="true" orientation="horizontal"></xui:Button>
<xui:Button x="0" y="3" width="1" height="1" id="button_1" label="Home"
enabled="true" orientation="horizontal"></xui:Button>
Tạo một ngôn ngữ mô tả UI XML
Trang 14 của 23
ibm.com/developerWorks/vn/
developerWorks®
<xui:Button x="0" y="7" width="1" height="1" id="button_2"
label="Forward" enabled="true" orientation="horizontal"></xui:Button>
</xui:Panel>
<!-- For opening files. Only want to see html files -->
<xui:OpenFileDialog x="10" y="10" width="400" height="300"
id="filedialog_0" idref="window_0" visible="false">
<xui:Filter>html</xui:Filter>
<xui:Filter>htm</xui:Filter>
</xui:OpenFileDialog>
<!-- For saving files. Only want to save html files -->
<xui:SaveFileDialog x="10" y="10" width="400" height="300"
id="savedialog_0" idref="window_0" visible="false">
<xui:Filter>html</xui:Filter>
<xui:Filter>htm</xui:Filter>
</xui:SaveFileDialog>
<!-- Ask the user if they really want to quit -->
<xui:CustomDialog x="200" y="200" width="320" height="160"
id="customdialog_1" idref="window_0" name="Exit Purnama Browser"
modal="true" visible="false">
<xui:GridLayout width="1" height="1"></xui:GridLayout>
<xui:Panel x="0" y="0" width="1" height="1" id="panel_2"
name="Quit Panel" idref="customdialog_0">
<xui:GridLayout width="5" height="4"></xui:GridLayout>
<xui:Label id="label_0" x="1" y="1" width="3" height="1"
justified="center" text="Do you really want to exit?"></xui:Label>
<xui:Button x="2" y="1" width="1" height="1" id="button_3"label="Yes"
enabled="true" orientation="horizontal"></xui:Button>
<xui:Button x="2" y="3" width="1" height="1" id="button_4" label="No"
enabled="true" orientation="horizontal"></xui:Button>
</xui:Panel>
</xui:CustomDialog>
<!-- For displaying the bookmarks -->
<xui:CustomDialog x="100" y="100" width="300" height="300"
id="customdialog_0" idref="window_0" name="Bookmarks" modal="false"
visible="false">
<xui:GridLayout width="1" height="1"></xui:GridLayout>
<xui:Panel x="0" y="0" width="1" height="1" id="panel_1"
name="bookmarks panel" idref="customdialog_0">
<xui:GridLayout width="1" height="1"></xui:GridLayout>
<xui:List x="0" y="0" width="1" height="1" id="list_0" enabled="true"
itemSelected="0" scrolling="vertical">
<xui:ListItem>http://www.w3c.org</xui:ListItem>
<xui:ListItem>http://www.agentcities.org</xui:ListItem>
<xui:ListItem>http://www.apache.org</xui:ListItem>
<xui:ListItem>http://www.gnu.org</xui:ListItem>
</xui:List>
</xui:Panel>
</xui:CustomDialog>
<!-- The menu bar with pop-up menu items too -->
<xui:MenuBar id="menuBar_0" idref="window_0">
<xui:Menu id="menu_0" idref="menuBar_0" enabled="true"
isPopupMenu="false" isSubMenu="false" label="File">
<xui:MenuItem id="mi_1" idref="menu_0" enabled="true" label="Open URL"
checked="false">
<xui:Shortcut keyCode="F" keyModifier1="ALT"></xui:Shortcut>
</xui:MenuItem>
<xui:MenuItem id="mi_0" idref="menu_0" enabled="true" label="Save"
checked="false">
<xui:Shortcut keyCode="F" keyModifier1="ALT"></xui:Shortcut>
</xui:MenuItem>
<xui:MenuItem id="mi_2" idref="menu_0" enabled="true" label="Exit"
checked="false">
Tạo một ngôn ngữ mô tả UI XML
Trang 15 của 23
developerWorks®
ibm.com/developerWorks/vn/
<xui:Shortcut keyCode="X" keyModifier1="CTRL"></xui:Shortcut>
</xui:MenuItem>
</xui:Menu>
<xui:Menu id="menu_1" idref="menuBar_0" enabled="true"
isPopupMenu="false" isSubMenu="false" label="Bookmarks">
<xui:MenuItem id="mi_3" idref="menu_1" enabled="true"
label="Add Bookmark" checked="false">
<xui:Shortcut keyCode="D" keyModifier1="CTRL"></xui:Shortcut>
</xui:MenuItem>
<xui:MenuItem id="mi_4" idref="menu_0" enabled="true"
label="Manage Bookmarks" checked="false">
<xui:Shortcut keyCode="M" keyModifier1="CTRL"></xui:Shortcut>
</xui:MenuItem>
</xui:Menu>
<xui:Menu id="menu_2" idref="hyper_0" enabled="true" isPopupMenu="true"
isSubMenu="false" label="">
<xui:MenuItem id="mi_5" idref="menu_2" enabled="true"
label="Save As ..." checked="false"></xui:MenuItem>
<xui:MenuItem id="mi_6" idref="menu_2" enabled="true" label="Previous"
checked="false"></xui:MenuItem>
<xui:MenuItem id="mi_7" idref="menu_2" enabled="true" label="Next"
checked="false"></xui:MenuItem>
<xui:MenuItem id="mi_8" idref="menu_2" enabled="true" label="Home"
checked="false"></xui:MenuItem>
<xui:MenuItem id="mi_9" idref="menu_2" enabled="true" label="Bookmark"
checked="false"></xui:MenuItem>
</xui:Menu>
</xui:MenuBar>
</xui:Window>
<!-- The library (model) code that drives the user interface -->
<xui:Resource type="java" class="BrowserModel" uri="BrowserModel.jar"/>
</xui:XUI>
Dĩ nhiên, không có trình duyệt nào có giá trị mà không có sự tương tác người dùng, nó ở bên cạnh.
Logic mô hình mã Java trình duyệt Web
Trong Liệt kê 8, phần tử Resource chứa tên của lớp mà hoạt động như một điểm vào mô hình ứng
dụng. Tên được cho là BrowserModel và như vậy, trên phần Java còn lại, liên tục, tên của lớp được
biên dịch phải phù hợp. Nó gồm không gian tên mà, trong trường hợp này là không gian tên mặc
định.
Bất kỳ lớp nào do đó cũng có thể hoạt động như điểm vào phần mô hình của ứng dụng cho đến khi
tên của nó cũng giống như giá trị thuộc tính class của phần tử Resource. Để tương tác người dùng
được buộc chính xác vào thời gian chạy, lớp đang thực hiện phải theo một số nguyên tắc sau:
• Có một phương thức với ký hiệu sau đây: public void init(XUI document).
• Thực hiện giao diện xử lý sự kiện phù hợp để nghe các sự kiện (chẳng hạn như ActionModel để
cài đặt các XUIButton).
• Sử dụng các giá trị id của các phần tử XML để tham khảo các thành phần GUI. (Việc này có
thể tực hiện bằng cách sử dụng một vài phương thức khác nhau tìm thấy trong lớp XUI.)
• Tự bổ sung như một thính giả vào thành phần thích hợp. Tất cả các thành phần tạo sự kiện
trong khung làm việc này, chẳng hạn như cài đặt lớp XUIButton thực hiện XUIEventSource, và
do đó, tạo các sự kiện UI.
Tạo một ngôn ngữ mô tả UI XML
Trang 16 của 23
ibm.com/developerWorks/vn/
developerWorks®
Trong Liệt kê 9, lớp BrowserModel thực hiện khởi tạo của nó trong phương thức init. Việc
này gồm việc tham chiếu đến các thành phần qua các giá trị id, tạo các mục của trình đơn
chứa các đánh dấu URL Web, và tự bổ sung như một thính giả vào thành các phần thông qua
phương thức addEventListener. BrowserModel có thể tự bổ sung như một thính giả vì nó là
một XUIModel (ActionModel là một kiểu con của XUIModel). Nó cũng đáng được đề cập là lớp
XUIComponentFactory đưa ra nhiều phương thức để tạo các thành phần XUI.
Liệt kê 9. Liệt kê mã bộ phận: khởi tạo
...
import org.purnamaproject.xui.binding.ActionModel;
...
public class BrowserModel implements ActionModel, TextModel, WindowModel,
ListActionModel {
...
private XUI xui;
...
public void init(XUI document) {
xui = document;
...
bookmarksList = (XUIList)xui.getXUIComponent("list_0");
homeButton = (XUIButton)xui.getXUIComponent("button_1");
...
List bookmarks = bookmarksList.getItems();
for(int i = 0; i < bookmarks.size(); i++) {
String url = (String)bookmarks.get(i);
XUIMenuItem aMenuItem = XUIComponentFactory.makeMenuItem(url);
bookmarksMenu.addMenuItem(aMenuItem);
linkModel.addSource(aMenuItem);
aMenuItem.addEventListener(linkModel);
}
...
homeButton.addEventListener(this);
...
}
...
}
Đi sâu hơn nữa, Liệt kê 10 trình bày mã xử lý sự kiện cho các thành phần khác nhau. Ví dụ:
• openMenuItem sẽ làm cho một fileDialog xuất hiện (một hội thoại theo kiểu để mở một trang
Web được lưu cục bộ).
• homeButton và popuphomeMenuItem (nhấn chuột phải để truy cập trong Window) cả hai thành
phần gọi ra phương thức doHome cho phép điều khiển trực tiếp trình duyệt đến giá trị thuộc tính
uri của phần tử HypertextPane (từ Liệt kê 8).
• fileDialog sẽ nạp một tệp mới và sau đó tăng biến index mà được sử dụng bởi queue của ứng
dụng để theo dõi các trang Web được vào trước đó.
Liệt kê 10. Liệt kê mã bộ phận: Xử lý sự kiện
public void action(XUIComponent component)
{
if(component == openMenuItem) {
fileDialog.setVisible(true);
} else if(component == homeButton || component == popuphomeMenuItem) {
doHome();
Tạo một ngôn ngữ mô tả UI XML
Trang 17 của 23
developerWorks®
ibm.com/developerWorks/vn/
} else if(component == prevButton || component == popupprevMenuItem) {
doPrevious();
} else if(component == nextButton || component == popupnextMenuItem) {
doNext();
} else if(component == fileDialog) {
if(fileDialog.getSelectedFile() !=null)
hyperTextPane.setURL(fileDialog.getSelectedFileAsURL());
index++;
if(index != queue.size()) {
nextButton.setEnabled(false);
popupnextMenuItem.setEnabled(false);
for(int i = index; i < queue.size(); i++) {
queue.remove(i);
}
}
queue.add(hyperTextPane.getURL());
prevButton.setEnabled(true);
popupprevMenuItem.setEnabled(true);
} else if(component == saveDialog) {
try {
FileOutputStream fos = new FileOutputStream(saveDialog.getSelectedFile());
hyperTextPane.getDocument().writeTo(fos);
} catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
}
} else if(component == popupsaveasMenuItem || component == saveMenuItem) {
saveDialog.setVisible(true);
} else if(component == popupbookmarkMenuItem || component == bookmarkMenuItem) {
doBookmark(hyperTextPane.getURL());
} else if(component == notDontExit) {
exitDialog.setVisible(false);
browserWindow.setVisible(true);
} else if(component == yesExit) {
System.exit(0);
} else if(component == exitMenuItem) {
exitDialog.setVisible(true);
} else if(component == manageBookmarksMenuItem) {
bookmarksDialog.setVisible(true);
}
}
Ứng dụng cuối cùng (trong Hình 2) trình bày một trình duyệt Web cơ sở cho phép bạn hiển thị các
trang cục bộ, các trang dựa trên web, và các trang Web được vào trước đó, cộng với khả năng quản
lý các đánh dấu.
Tạo một ngôn ngữ mô tả UI XML
Trang 18 của 23
ibm.com/developerWorks/vn/
developerWorks®
Hình 2. Ảnh chụp màn hình của trình duyệt Web
Bạn sẽ tìm thấy một vài mẫu ứng dụng khác trong mục Tải về cho bài này.
Các hiểu biết và thách thức
Giải pháp này hứng thú, cách tiếp cận khá lý tưởng: các vấn đề về an toàn trong khung làm việc
này đã được bỏ qua. Gọi lại các API nạp vô hại một tệp JAR từ bất kỳ URI nào. Gọi lại phần tử
Resource hiển thị trong Liệt kê 8. Kiểu này theo nghĩa đen là anyURI. Nó có nghĩa là tệp cục bộ, tệp
trên mạng, tệp trên Internet. Bất cứ đâu. Một ứng dụng có nên tin cậy vào các quy tắc nghiệp vụ ở
bất kỳ nơi nào không? Rõ ràng là bạn muốn xem xét một số loại hình mẫu an ninh để hạn chế việc
nạp các tài nguyên không tin cậy. Một cách để nhằm vào vấn đề này là hạn chế các URI để tham
chiếu một bảng tra cứu. Giải pháp khác (sạch sẽ hơn) là sử dụng các giấy chứng nhận kiểu số.
Cuối cùng, cân nhắc việc nạp của các định dạng XML khác theo định dạng UI XML mô tả này. Lược
đồ XML hỗ trợ việc này tùy theo việc sử dụng các không gian tên được yêu cầu. Thí dụ bạn có thể
nhúng vào một định dạng XML riêng rẽ để trình bày đồ thị véc-tơ có thể phóng to thu nhỏ được
(scalable vector graphics) trong tài liệu XML.
Kết luận
Bài viết này đề cập đến định nghĩa một ngôn ngữ UI XML mô tả và nó trông như thế nào. Nó giới
thiệu một khung làm việc Java đi kèm cũng như mẫu ứng dụng — trình duyệt Web. Cuối cùng, nó
đưa ra các vấn đề an toàn và các mối quan tâm.
Việc tạo các UI XML mô tả chắc chắn là không mới. Tuy nhiên nó là một lĩnh vực phát triển phần
mềm đang trưởng thành và trở nên phổ biến hơn. Một bổ sung nữa là việc tạo các UI XML mô tả
giúp thúc đẩy việc tái sử dụng phần mềm và tính mô-đun.
Tạo một ngôn ngữ mô tả UI XML
Trang 19 của 23
developerWorks®
ibm.com/developerWorks/vn/
Các tải về
Mô tả
XUI XSD and Java API for article
1
Tên
Kích thước
xui.zip
30KB
Ghi chú
1. Tệp.zip này chứa toàn bộ mã nguồn cho dự án này, tệp dựng Apache Ant, lược đồ XML, các thí dụ, và các thư viện bên thứ ba (các JAR) mà
bài viết này tham khảo và sử dụng.
Tạo một ngôn ngữ mô tả UI XML
Trang 20 của 23
ibm.com/developerWorks/vn/
developerWorks®
Tài nguyên
Học tập
• Lược đồ XML Phần 0: Hướng dẫn nhập môn: Khởi động tốt về việc tìm hiểu lược đồ XML trong
sách nhập môn về W3C.
• Lược đồ XML Phần 1: Cấu trúc: Tìm hiểu cấu trúc dữ liệu trong lược đồ XML.
• Lược đồ XML Phần 2: Các kiểu dữ liệu: Xem chương W3C này về các kiểu dữ liệu được định
nghĩa trong lược đồ XML.
• Tài liệu hướng dẫn về Swing: Hãy nhận tài liệu hướng dẫn trực tuyến của Sun đề cập sâu đến
cách phát triển các GUI dùng cho các ứng dụng và các tiện ích trong Swing.
• Mô hình Đối tượng Tài liệu (DOM) trên W3C: Tìm hiểu nhiều hơn về Mô hình Đối tượng Tài
liệu W3C trong tổng quan này của tài liệu liên quan đến DOM.
• Base64 data (Wikipedia): Đọc bài giải thích hay về việc mã hóa Base64.
• XAML: Tìm hiểu nhiều hơn về XAML.
• Định dạng MXML: Tìm hiểu nhiều hơn về này định dạng Adobe.
• Các khái niệm cơ sở về cách sử dụng Lược đồ XML để định nghĩa các phần tử (Ashvin Radiya
và Vibha Dixit, developerWorks, 8.2000): Đọc giới thiệu hay về lược đồ XML và bắt đầu sử
dụng lược đồ XML thay vì các DTD để định nghĩa cấu trúc của các tài liệu XML.
• Gợi ý: làm việc với các lược đồ và không gian tên (Brett McLaughlin, developerWorks,
9.2002): Làm sáng tỏ phạm vi vùng tên trong lược đồ XML, gồm nhiều vùng tên.
• Liên kết dữ liệu với Castor, Phần 2: tổ chức lưu dữ liệu và bỏ tổ chức lưu dữ liệu XML (Brett D.
McLaughlin, Sr., developerWorks, 12.2007): Đọc một bài viết hay mô tả cách tổ chức lưu dữ
liệu và bỏ tổ chức lưu dữ liệu thông qua sử dụng Castor.
• Cấp chứng nhận XML của IBM: Tìm ra cách bạn có thể trở thành một nhà phát triển được IBM
chứng nhận về công nghệ XML và các công nghệ liên quan.
• Thư viện kỹ thuật XML: Xem Lĩnh vực XML của developerWorks để có nhiều bài viết và mách
nước về kỹ thuật, các hướng dẫn, tiêu chuẩn, và các sách đỏ của IBM.
• Các buổi phát tin trên mạng và các sự kiện kỹ thuật của developerWorks: Theo sát công nghệ
về các mục này.
• Nhà sách công nghệ: Duyệt các cuốn sách về chủ đề này và các chủ đề kỹ thuật khác.
• Các bài phát thanh trên mạng của developerWorks: Nghe các phỏng vấn thú vị và thảo luận
dành cho các nhà phát triển phần mềm.
Lấy sản phẩm và công nghệ
• Glade: Tìm hiểu nhiều hơn về và tải về Glade, một công cụ RAD để cho phép phát triển
nhanh chóng, dễ dàng các UI dùng cho GTK + bộ công cụ và môi trường máy tính bàn
GNOME.
• Các phiên bản đánh giá sản phẩm của IBM: Tải về hoặc khám phá trực tuyến các thử nghiệm
trong IBM SOA Sandbox và nhận các công cụ phát triển ứng dụng thực hành và các sản
phẩm phần giữa từ DB2®, Lotus®, Rational®, Tivoli®, và WebSphere®.
Thảo luận
• Các diễn đàn thảo luận về lĩnh vực XML: Tham gia vào bất kỳ thảo luận nào liên quan đến
XML.
Tạo một ngôn ngữ mô tả UI XML
Trang 21 của 23
developerWorks®
ibm.com/developerWorks/vn/
• Các blog developerWorks: xem các blog và gia nhập cộng đồng developerWorks.
Tạo một ngôn ngữ mô tả UI XML
Trang 22 của 23
ibm.com/developerWorks/vn/
developerWorks®
Đôi nét về tác giả
Arron Ferguson
Arron Ferguson là một giảng viên đại học đã 12 năm, dạy về kỹ thuật phần mềm tại
Viện Công nghệ British Columbia. Các lĩnh vực kinh nghiệm và quan tâm của ông
là công nghệ Java, XML, các công nghệ Web, hoạt hình 2D và 3D, và viết cho các
phương tiện truyền thông kỹ thuật số. Ông là soạn giả và nhà phê bình kỹ thuật tự
do và có cuốn sách được xuất bản: Tạo Các Hệ thống Quản trị Nội dung trong Java
(Creating Content Management Systems in Java) (Charles River Media, 2006). Arron
cũng say mê Linux và công nghệ mã nguồn mở khác.
© Copyright IBM Corporation 2009
(www.ibm.com/legal/copytrade.shtml)
Nhẫn hiệu đăng ký
(www.ibm.com/developerworks/vn/ibm/trademarks/)
Tạo một ngôn ngữ mô tả UI XML
Trang 23 của 23