1 概 述 隨著(zhù)嵌入式系統的廣泛應用,圖形用戶(hù)界面(Graphical User Interface,GUI)在嵌入式系統中的地位也越來(lái)越重要。 目前比較成熟的嵌入式GUI系統包括MicroWin-dows、Qt/Embedded、MiniGUI等。MicroWindows可移植性好,開(kāi)發(fā)重點(diǎn)在底層的圖形引擎,但窗口系統和圖形接口方面的功能還比較欠缺。Qt/Embedded可移植性較好,基于Qt的X Window程序可以非常方便地移植到嵌入式系統,但對系統硬件要求較高,主要用于手持設備。MiniGUI最初是為了工業(yè)控制系統設計開(kāi)發(fā)的,定制能力強,速度快,性能好,特別適合于實(shí)時(shí)性要求高的場(chǎng)合。由于受到嵌入式系統硬件資源的限制,對嵌入式系統GUI的基本要求包括:占用資源少、高性能、高可靠性、可配置。本文設計的可視化開(kāi)發(fā)工具選擇MiniGUI作為圖形界面支持系統。 MiniGUI是一款遵循LGPL條款的純自由軟件,是根據嵌入式系統應用特點(diǎn)量身定做的圖形界面支持系統,得到了廣泛應用。它提供了完備的多窗口機制和消息傳遞機制,以及對話(huà)框和常用的控件類(lèi),包括文本框、按鈕、編輯框、列表框等;非常小巧,包含全部功能的庫文件僅為300 KB左右。傳統的MiniGUI程序開(kāi)發(fā)是基于文本編輯器的,開(kāi)發(fā)人員在程序源代碼編寫(xiě)過(guò)程中無(wú)法預先看到窗口、控件的整體效果,缺乏一個(gè)可視化的開(kāi)發(fā)環(huán)境。因此,本文設計了一個(gè)MiniGUI可視化開(kāi)發(fā)工具,并使用Eclipse GEF(Graphical Editing Framework)實(shí)現。 2 可視化開(kāi)發(fā)工具整體設計 2.1 功能需求 可視化開(kāi)發(fā)工具要提供界面布局設計功能,主要包括:界面上控件位置的擺放、屬性的設置,為每個(gè)控件定義callback函數;菜單、狀態(tài)條、位圖編輯;響應界面編輯過(guò)程中發(fā)生的交互事件,比如drop/drag、undo/redo、move、de-lete、resize等;保存及解析呈現相應布局的功能;根據用戶(hù)設計生成可運行的MiniGUI源代碼。 2.2 整體結構 可視化開(kāi)發(fā)工具主要由界面設計工具和源代碼生成工具兩部分組成。整體結構如圖1所示。 界面設計工具:實(shí)現所見(jiàn)即所得的界面編輯器功能,可以根據需要改變和調整顯示的內容和形式,這使得用戶(hù)界面的制作非常方便。采用傳統的面向對象設計方法來(lái)開(kāi)發(fā)可視化界面,會(huì )遇到用戶(hù)界面和底層的數據雜合、接口擴展導致的類(lèi)膨脹等問(wèn)題,因此界面設計工具使用MVC模式設計。用戶(hù)通過(guò)界面設計工具的“控件設計”設置控件屬性;“交互事件響應”用于響應界面編輯過(guò)程中發(fā)生的交互事件,完成控件屬性的修改。這兩部分對應MVC中的Control-ler!翱丶(lèi)”保存控件的各種屬性,對應Model!翱丶@示”根據控件類(lèi)的屬性設置顯示控件,對應View。XML文檔則負責保存界面布局,控件類(lèi)也能夠根據XML解析文檔內容得到自身屬性。 源代碼生成工具:通過(guò)遍歷所有控件類(lèi)的屬性,將圖形用戶(hù)界面布局按照運行平臺要求(目前僅支持RTEMS)生成相應的MiniGUI源代碼。 2.3 組織結構 所有控件類(lèi)通過(guò)樹(shù)的形式來(lái)管理。樹(shù)的頂層表示一個(gè)管理的工程,其下包括所有的對話(huà)框、菜單、狀態(tài)條及位圖資源,對話(huà)框的子節點(diǎn)是其上顯示的所有控件,菜單包括彈出菜單和菜單項,狀態(tài)條與對話(huà)框類(lèi)似,樹(shù)形結構如圖2所示。由于XML文檔會(huì )被Java解析成樹(shù)形結構,解析界面布局的過(guò)程就是一個(gè)樹(shù)的遍歷過(guò)程。使用樹(shù)形結構來(lái)組織控件類(lèi),能夠讓軟件在邏輯上簡(jiǎn)單易懂,控件組織關(guān)系清晰明了,并且通過(guò)樹(shù)的遍歷可以保存界面布局及生成源代碼。 由于圖形用戶(hù)界面中許多元素具有共同屬性,本文把這些元素的共有屬性及方法抽象出來(lái)作為基類(lèi)。主要使用2個(gè)基類(lèi):容器類(lèi)Content和控件類(lèi)Control。Content主要包括容器ID、文字屬性及保存解析控件等方法;Control主要包括控件ID、位置大小、控件風(fēng)格等屬性,以及保存解析控件、生成源代碼等方法。其中,對話(huà)框、菜單、狀態(tài)條和位圖繼承自Content,如圖3(a)所示;對話(huà)框控件繼承自Control,如圖3(b)所示。在生成源代碼等操作時(shí)自頂向下遍歷整個(gè)界面工程,可直接調用基類(lèi)的方法,無(wú)需區分控件具體的類(lèi)別。這樣提高了代碼的重用度,減少了冗余代碼。 3 系統實(shí)現 GEF基于MVC框架,可以方便地實(shí)現drop/drag、undo/redo、move、delete、resize等圖形編輯器的基本功能,并且提供了常用的布局器,非常適合用于開(kāi)發(fā)所見(jiàn)即所得的界面編輯器。其中,GEF的EditPart對應MVC中的Controller,Figure對應View。 本工具基于GEF開(kāi)發(fā),可以最大限度地減小開(kāi)發(fā)工作量,增強軟件的穩定性。同時(shí),Java開(kāi)發(fā)使得本工具可以在任何具有Java虛擬機的系統上運行,具有良好的跨平臺性。 3.1 基于GEF實(shí)現的界面設計工具 本工具提供對菜單、狀態(tài)條、位圖,以及對話(huà)框控件(包括CheckBox, ComboBox,Pushbutton, RadioButton,MonthCalendar,GridView,M1Edit,ProgressBar,Property-Sheet,Static,StaticBox,TreeView,TrackBar,SpinBox等)的編輯功能。對于控件的修改,可以通過(guò)屬性頁(yè)和在界面上直接操作來(lái)進(jìn)行。屬性頁(yè)上的編輯通過(guò)IPropertySource接口的setPropertyValue方法告知Model,Model再通過(guò)PropertyChangeSupport類(lèi)的firePropertyChange方法通知EditPart做出修改;來(lái)自界面上的變化被封裝成request派發(fā)給EditPart,EditPart再通過(guò)command修改Model中的數據,Model在修改完數據之后告知EditPart有數據被修改;EditPart收到Property改變的通知后,根據修改數據類(lèi)型做出相應操作(比如重繪figure等)。以對CheekBox的操作為例來(lái)說(shuō)明基于GEF的控件處理流程,如圖4所示。其中,操作A是從工具箱拖拽一個(gè)新的CheckBox到Dialog中;操作B是通過(guò)屬性頁(yè)修改CheckBox顯示的文本(Text);操作C直接通過(guò)選中CheckBox拖拽改變其大小。操作A1~A4、B1~B3、C1~C3為具體的執行流程。 3.2 圖形顯示問(wèn)題 在GEF中,每個(gè)視圖只有在其父視圖的有效范圍內才能響應交互事件。如果直接按照MiniGUI的控件關(guān)系來(lái)組織模型,則界面設計工具不能很好地完成與用戶(hù)的交互。 以菜單為例,生成MiniGUI中菜單部分的代碼僅需完成一棵樹(shù)的遍歷。這棵樹(shù)的每個(gè)非葉節點(diǎn)都是一個(gè)彈出菜單,葉節點(diǎn)是普通的菜單項,根節點(diǎn)是一個(gè)虛節點(diǎn),用于串連起整個(gè)菜單,如圖5(a)所示。每個(gè)節點(diǎn)都被稱(chēng)作MenuItem。這種樹(shù)形結構在GEF顯示時(shí)根據Model創(chuàng )建的Figure如圖5(b)所示,其中Figure11為Figure1的childFigure。在GEF中,只有childFigure被包含在parentFigure的有效范圍內,對childFigure提出的請求才能被其parentFigure派發(fā)給childFigure對應的control-ler,并反映給Model,如圖5(c)所示。顯然樹(shù)形結構無(wú)法滿(mǎn)足修改菜單項的需求,因此,在MenuItem構成的樹(shù)形結構基礎上增加了由MeInu組成的鏈表結構,同時(shí)每個(gè)MenuItem都增加一個(gè)指向自己上一級MenuItem的Par-ent指針,如圖5(d)所示。每個(gè)Menu(ij)記錄包括的所有MenuItem(ij,k),以及創(chuàng )建自己的Menultem(i,j)。MenuItem(ij,k)表示屬于Menu(ij)的第k個(gè)MenuItem,Menu(ij)表示MenuItem(i,j)展開(kāi)的下級Menu。所有的Menu組成一個(gè)鏈表,GEF顯示的是這個(gè)鏈表的內容,而不是原來(lái)的MenuItem樹(shù)。這樣,每個(gè)MenuItem對應的Figure就可以包含在其parentFigure中,相應的controller也就能夠收到界面上傳來(lái)的請求。 將MenuItem屬性改變?yōu)镻opUp,可以為其建立下級子Menu。新建函數的流程如下(參數是當前屬性修改為PopUp的MenuItem): MenuItem對應的Figure還應提供方法DimensiongetPreferredSize(int hint,int hint2),用于獲得MenuItem屬性改變導致的Figure新的大小和位置。 ①重繪自己和下面所有的MenuItem及其下級的Menu。函數Rectangle CalcMenuSize(MenuEditPart)用于得到一個(gè)能夠容納下包括的所有MenuItem的矩形。 ②遞歸地將要update的MenuEditPart的下級Menu中,當前可見(jiàn)的所有Menu及其對應的MenuItem變?yōu)椴豢梢?jiàn)。 3.3 數據存儲 可擴展標記語(yǔ)言(Extensible Markup Language,XML)與其他格式的語(yǔ)言相比,具有以下優(yōu)勢:具有良好的擴展性,允許使用者創(chuàng )建和使用自己定義的標記來(lái)定義控件的類(lèi)型和屬性;樹(shù)狀存儲結構和良好的自描述性,非常適合對界面元素進(jìn)行描述;XML的靈活性提供了一種結構化的數據表示方式,使得用戶(hù)界面分離于結構化數據。 因此,界面設計工具將界面設計結果存儲為XML格式。由于Java中提供了XML文檔生成和解析的類(lèi),因而簡(jiǎn)化了編碼工作量,增強了軟件可靠性。 示例如下: 最外層的Project表示內層都是界面的布局,第2層Dialog表示其內層對應一個(gè)對話(huà)框布局,第3層由多個(gè)和對構成(XXCtrl對應不同的控件名,比如buttonCtrl對應button控件)。每個(gè)XXCtrl代表一個(gè)控件,和對里面是控件的屬性。第2層也可由多個(gè)和對構成,Content可為Dialog(對話(huà)框)、Menu(菜單)、Tool-Bar(狀態(tài)條)、Icon(位圖),其內層根據Content不同而由不同的XXCtrl對構成。 4 實(shí)驗結果 可視化工具的運行界面如圖6所示。左側為工程管理區,可以看到當前工程建立的所有界面布局。中間部分的編輯區是一個(gè)打開(kāi)的對話(huà)框布局,可在這里進(jìn)行控件的drop/drag、undo/redo、move、delete、resize等操作。右側是控件屬性編輯區,用于修改控件屬性(比如ID、文字風(fēng)格、邊框等)。 結 語(yǔ) 本文設計了一個(gè)MiniGUI可視化開(kāi)發(fā)工具,利用Eclipse GEF實(shí)現。用戶(hù)使用本工具可以對圖形用戶(hù)界面進(jìn)行可視化的設計及修改,同時(shí)可以擴充自己的控件、定義控件的屬性,豐富界面的表現形式。實(shí)驗表明,本工具在實(shí)際系統中運行良好穩定,有效地提高了圖形用戶(hù)界面的開(kāi)發(fā)效率。 |