sharky的點(diǎn)滴積累

            BlogJava :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理 ::
            56 隨筆 :: 104 文章 :: 10 評(píng)論 :: 0 Trackbacks

          在前面的帖子已經(jīng)提到,GEF(Graphical Editor Framework)是一個(gè)圖形化編輯框架,它允許開發(fā)人員以圖形化的方式展示和編輯模型,從而提升用戶體驗(yàn)。這樣的應(yīng)用程序有很多,例如:UML類圖編輯器、圖形化XML編輯器、界面設(shè)計(jì)工具以及圖形化數(shù)據(jù)庫結(jié)構(gòu)設(shè)計(jì)工具等等。歸結(jié)一下,可以發(fā)現(xiàn)它們?cè)趫D形化編輯方面具有以下共同之處:

          • 提供一個(gè)編輯區(qū)域和一個(gè)工具條,用戶在工具條里選擇需要的工具,以拖動(dòng)或單擊的方式將節(jié)點(diǎn)或連接放置在編輯區(qū)域;
          • 節(jié)點(diǎn)可以包含子節(jié)點(diǎn);
          • 用戶能夠查看和修改某個(gè)節(jié)點(diǎn)或連接的大部分屬性;
          • 連接端點(diǎn)錨定在節(jié)點(diǎn)上;
          • 提供上下文菜單和鍵盤命令;
          • 提供圖形的縮放功能;
          • 提供一個(gè)大綱視圖,顯示編輯區(qū)域的縮略圖,或是樹狀模型結(jié)構(gòu);
          • 支持撤消/重做功能;
          • 等等。

           
          圖1 基于GEF的界面設(shè)計(jì)工具(Visual Editor,VE)的工作界面

          GEF最早是Eclipse的一個(gè)內(nèi)部項(xiàng)目,后來逐漸轉(zhuǎn)變?yōu)镋clipse的一個(gè)開源工具項(xiàng)目,Eclipse的不少其他子項(xiàng)目都需要它的支持。Eclipse 3.0版本花了很大功夫在從Platform中剝離各種功能部件上,包括GEF和IDE在內(nèi)的很多曾經(jīng)只能在Eclipse內(nèi)部使用的工具成為可以獨(dú)立使用的軟件/插件包了。理論上我們是可以脫離Eclipse用GEF包構(gòu)造自己的應(yīng)用程序的,但由于它們之間天然的聯(lián)系,而且Eclipse確實(shí)是一個(gè)很值得支持的開發(fā)平臺(tái),所以我還是推薦你在Eclipse中使用它。

          GEF的優(yōu)勢是提供了標(biāo)準(zhǔn)的MVC(Model-View-Control)結(jié)構(gòu),開發(fā)人員可以利用GEF來完成以上這些功能,而不需要自己重新設(shè)計(jì)。與其他一些MVC編輯框架相比,GEF的一個(gè)主要設(shè)計(jì)目標(biāo)是盡量減少模型和視圖之間的依賴,好處是可以根據(jù)需要選擇任意模型和視圖的組合,而不必受開發(fā)框架的局限(不過實(shí)際上還是很少有脫離Draw2D的實(shí)現(xiàn))。

          現(xiàn)在來看看GEF是如何實(shí)現(xiàn)MVC框架的吧,在這個(gè)帖子里我們先概括介紹一下它的各個(gè)組成部分,以后將結(jié)合例子進(jìn)行更詳細(xì)的說明。


          圖2 GEF結(jié)構(gòu)圖

          模型:GEF的模型只與控制器打交道,而不知道任何與視圖有關(guān)的東西。為了能讓控制器知道模型的變化,應(yīng)該把控制器作為事件監(jiān)聽者注冊(cè)在模型中,當(dāng)模型發(fā)生變化時(shí),就觸發(fā)相應(yīng)的事件給控制器,后者負(fù)責(zé)通知各個(gè)視圖進(jìn)行更新。

          典型的模型對(duì)象會(huì)包含PropertyChangeSupport類型的成員變量,用來維護(hù)監(jiān)聽器成員即控制器;對(duì)于與其他對(duì)象具有連接關(guān)系的模型,要維護(hù)連入/連出的連接列表;如果模型對(duì)應(yīng)的節(jié)點(diǎn)具有大小和位置信息,還要維護(hù)它們。這些變量并不是模型本身必須的信息,維護(hù)它們使模型變得不夠清晰,但你可以通過構(gòu)造一些抽象模型類(例如讓所有具有連接的模型對(duì)象繼承Node類)來維持它們的可讀性。

          相對(duì)來講GEF中模型是MVC中最簡單的一部分。

          控制器:我們知道,在MVC結(jié)構(gòu)里控制器是模型與視圖之間的橋梁,也是整個(gè)GEF的核心。它不僅要監(jiān)聽模型的變化,當(dāng)用戶編輯視圖時(shí),還要把編輯結(jié)果反映到模型上。舉個(gè)例子來說,用戶在數(shù)據(jù)庫結(jié)構(gòu)圖上刪除一個(gè)表時(shí),控制器應(yīng)該從模型中刪除這個(gè)表對(duì)象、表中的字段對(duì)象、以及與這些對(duì)象有關(guān)的所有連接。當(dāng)然在GEF中這些操作不是由直接控制器完成的,這個(gè)稍后就會(huì)說到。

          GEF中的控制器是所謂的EditPart對(duì)象,更確切的說應(yīng)該是一組EditPart對(duì)象共同組成了GEF的控制器這部分,每一個(gè)模型對(duì)象都對(duì)應(yīng)一個(gè)EditPart對(duì)象。你的應(yīng)用程序中需要有一個(gè)EditPartFactory對(duì)象負(fù)責(zé)根據(jù)給定模型對(duì)象創(chuàng)建對(duì)應(yīng)的EditPart對(duì)象,這個(gè)工廠類將被視圖利用。

          RootEditPart是一種特殊的EditPart,它和你的模型沒有任何關(guān)系,它的作用是把EditPartViewer和contents(應(yīng)用程序的最上層EditPart,一般代表一塊畫布)聯(lián)系起來,可以把它想成是contents的容器。EditPartViewer有一個(gè)方法setRootEditPart()專門用來指定視圖對(duì)應(yīng)的RooEditPart。


          圖3 EditPart對(duì)象

          用戶的編輯操作被轉(zhuǎn)換為一系列請(qǐng)求(Request),有很多種類的請(qǐng)求,這些種類在GEF里被稱為角色(Role),GEF里有圖形化和非圖形化這兩大類角色,前者比如Layout Role對(duì)應(yīng)和布局有關(guān)的的操作,后者比如Connection Role對(duì)應(yīng)和連接有關(guān)的操作等等。角色這個(gè)概念是通過編輯策略(EditPolicy)來實(shí)現(xiàn)的,EditPolicy的主要功能是根據(jù)請(qǐng)求創(chuàng)建相應(yīng)的命令(Command),而后者會(huì)直接操作模型對(duì)象。對(duì)每一個(gè)EditPart,你都可以"安裝"一些EditPolicy,用戶對(duì)這個(gè)EditPart的特定操作會(huì)被交給已安裝的對(duì)應(yīng)EditPolicy處理。這樣做的直接好處是可以在不同EditPart之間共享一些重復(fù)操作。

          在GEF SDK提供的幫助文檔(GEF開發(fā)指南)里有一份詳細(xì)的EditPolicy、Role和Request類型列表,這里就不贅述了。

          視圖:前面說過,GEF的視圖可以有很多種,GEF目前提供了圖形(GraphicalViewer)和樹狀(TreeViewer)這兩種,前者利用Draw2D圖形(IFigure)作為表現(xiàn)方式,多用于編輯區(qū)域,后者則多用于實(shí)現(xiàn)大綱展示。視圖的任務(wù)同樣繁重,除了模型的顯示功能以外,還要提供編輯功能、回顯(Feedback)、工具提示(ToolTip)等等。

          GEF使用EditPartViewer作為視圖,它的作用和JFace中的Viewer十分類似,而EditPart就相當(dāng)于是它的ContentProvider和LabelProvider,通過setContents()方法來指定。我們經(jīng)常使用的Editor是一個(gè)GraphicalEditorWithPalette(GEF提供的Editor,是EditorPart的子類,具有圖形化編輯區(qū)域和一個(gè)工具條),這個(gè)Editor使用GraphicalEditViewer和PaletteViewer這兩個(gè)視圖類,PaletteViewer也是GraphicalEditViewer的子類。開發(fā)人員要在configureGraphicalViewer()和initializeGraphicalViewer()這兩個(gè)方法里對(duì)EditPartViewer進(jìn)行定制,包括指定它的contents和EditPartFactory等等。

          EditPartViewer同時(shí)也是ISelectionProvider,這樣當(dāng)用戶在編輯區(qū)域做選擇操作時(shí),注冊(cè)的SelectionChangeListener就可以收到選擇事件。EditPartViewer會(huì)維護(hù)各個(gè)EditPart的選中狀態(tài),如果沒有被選中的EditPart,則缺省選中的是作為contents的EditPart。

          初步了解了GEF的MVC實(shí)現(xiàn)方式,讓我們看看典型的GEF應(yīng)用程序是什么樣子的。大部分GEF應(yīng)用程序都實(shí)現(xiàn)為Eclipse的Editor,也就是說整個(gè)編輯區(qū)域是放置在一個(gè)Editor里的。所以典型的GEF應(yīng)用程序具有一個(gè)圖形編輯區(qū)域包含在一個(gè)Editor(例如GraphicalEditorWithPalette)里,可能有一個(gè)大綱視圖和一個(gè)屬性頁,一個(gè)用于創(chuàng)建EditPart實(shí)例的EditPartFactory,一些表示業(yè)務(wù)的模型對(duì)象,與模型對(duì)象對(duì)應(yīng)的一些EditPart,每個(gè)EditPart對(duì)應(yīng)一個(gè)IFigure的子類對(duì)象顯示給用戶,一些EditPolicy對(duì)象,以及一些Command對(duì)象。

          GEF應(yīng)用程序的工作方式如下: EditPartViewer接受用戶的操作,例如節(jié)點(diǎn)的選擇、新增或刪除等等,每個(gè)節(jié)點(diǎn)都對(duì)應(yīng)一個(gè)EditPart對(duì)象,這個(gè)對(duì)象有一組按操作Role分開的EditPolicy,每個(gè)EditPolicy會(huì)對(duì)應(yīng)一些Command對(duì)象,Command最終對(duì)模型進(jìn)行直接修改。用戶的操作轉(zhuǎn)換為Request分配給適當(dāng)?shù)腅ditPolicy,由后者創(chuàng)建適當(dāng)?shù)腃ommand來修改模型,這些Command會(huì)保留在EditDomain(專門用于維護(hù)EditPartViewer、Command等信息的對(duì)象,一般每個(gè)Editor對(duì)應(yīng)唯一一個(gè)該對(duì)象)的命令堆棧里,用于實(shí)現(xiàn)撤消/重做功能。

          以上介紹了GEF中一些比較重要的概念,不知道看過之后你是否對(duì)它有了一個(gè)大概的印象。如果沒有也沒關(guān)系,因?yàn)樵诤竺娴奶永飳?huì)有結(jié)合例子的講解,我們使用的實(shí)例就是序言里提到的第六個(gè)項(xiàng)目。

          參考資料:

          • GEF開發(fā)指南
          • Eclipse Development - Using the Graphical Editing Framework and the Eclipse Modeling Framework
          posted on 2005-02-13 15:21 八進(jìn)制 閱讀(2155) 評(píng)論(11)  編輯 收藏 收藏至365Key 所屬分類: Eclipse

          評(píng)論

          # re: [Eclipse]GEF入門系列(二、GEF概述) 2005-02-18 19:01 郭奕
          寫得很好,很清楚。比redbook好多了。繼續(xù)!期盼中。。。謝謝。
            

          # re: [Eclipse]GEF入門系列(二、GEF概述) 2005-02-18 23:32 八進(jìn)制
          不用客氣啦,還請(qǐng)多提意見。
            

          # re: [Eclipse]GEF入門系列(二、GEF概述) 2005-03-07 12:32 howjay
          “大部分GEF應(yīng)用程序都實(shí)現(xiàn)為Eclipse的Editor,也就是說整個(gè)編輯區(qū)域是放置在一個(gè)Editor里的。”

          意思是基本上都要Eclipse的支持嗎?我用過VE,UML的畫圖,確實(shí)是需要Eclipse的。那能不能脫離Eclipse呢?
            

          # re: [Eclipse]GEF入門系列(二、GEF概述) 2005-04-07 20:15 Tim
          hi, 請(qǐng)問哪里可以搞到"GEF開發(fā)指南"呢?如果你手上有的話,發(fā)一份給我好嗎:woobeen@msn.com,謝謝!
            

          # re: [Eclipse]GEF入門系列(二、GEF概述) 2005-04-07 22:49 八進(jìn)制
          帖子里說的開發(fā)指南是GEF幫助,“GEF Developer Guide”,安裝GEF以后在Eclipse幫助里就可以看到。
            

          # re: [Eclipse]GEF入門系列(二、GEF概述) 2005-08-25 16:47 sawxb
          十分感謝八進(jìn)制的blog,更要感謝八進(jìn)制,在這里我學(xué)會(huì)了很多東西,幾乎是你在寫到這片文章的時(shí)候我剛剛開始學(xué)習(xí)GEF,中文資料幾乎沒有,我完全是在你的這些文章的幫助下學(xué)習(xí)的GEF。現(xiàn)在剛剛畢業(yè),公司也不算很忙,打算深入的研究一下GEF。
          上次在你的指點(diǎn)下,很快就把問題解決了,而且是在幾個(gè)小時(shí)后就幫我解答了,真是神速啊,太強(qiáng)了。

          請(qǐng)問八進(jìn)制,在model包中Element類中的

          private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
          in.defaultReadObject();
          listeners = new PropertyChangeSupport(this);
          }
          這個(gè)方法具體事做什么的,我看好像沒有地方需要這個(gè)東西啊,麻煩你幫我看一下,先謝謝了。
            

          # re: [Eclipse]GEF入門系列(二、GEF概述) 2005-08-25 17:10 八進(jìn)制
          你說的是哪個(gè)model包,應(yīng)該不是gef里的吧?
            

          # re: [Eclipse]GEF入門系列(二、GEF概述) 2005-08-25 18:29 sawxb
          subject 項(xiàng)目中的

            

          # re: [Eclipse]GEF入門系列(二、GEF概述) 2005-08-25 18:33 sawxb
          是GEF中的,就是你編寫的subject 項(xiàng)目實(shí)例中的 model包中 Element 類 中的方法
            

          # re: [Eclipse]GEF入門系列(二、GEF概述) 2005-08-25 20:57 八進(jìn)制
          看到了,這個(gè)方法是以前方便序列化/反序列化用的,現(xiàn)在已經(jīng)不用了,呵呵。
          在Eclipse里查找它的reference就會(huì)發(fā)現(xiàn)沒有任何類使用到它。
            

          # re: [Eclipse]GEF入門系列(二、GEF概述) 2005-08-25 21:39 sawxb
          謝謝,八進(jìn)制!!在以前,我都是只看代碼,所以現(xiàn)在想從頭自己研究一下GEF,以便徹底搞清楚GEF這東西。

          posted on 2005-08-26 17:06 sharky的點(diǎn)滴積累 閱讀(605) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 神木县| 普兰店市| 长丰县| 青浦区| 南投县| 武城县| 沐川县| 万宁市| 崇文区| 咸阳市| 肃宁县| 五家渠市| 香河县| 尼勒克县| 樟树市| 滦平县| 和静县| 珠海市| 颍上县| 顺平县| 河池市| 五河县| 三都| 庆云县| 宣化县| 沈丘县| 洪洞县| 莱阳市| 乌鲁木齐县| 河南省| 大城县| 丰县| 福清市| 麻栗坡县| 山阴县| 沁水县| 阿合奇县| 油尖旺区| 碌曲县| 吴堡县| 青川县|