<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    weidagang2046的專欄

    物格而后知致
    隨筆 - 8, 文章 - 409, 評論 - 101, 引用 - 0
    數據加載中……

    使用圖形編輯框架創建基于 Eclipse 的應用程序

    本文為您從頭到尾地介紹了使用 GEF 的步驟。我們不是完整地完成每個步驟,而是將使用您的應用程序模型的子集,并先使該子集工作。例如,開始我們可能會忽略連接,或者只注重于您應用程序中圖形元素類型的子集。

    GEF 概述

    GEF 假定您擁有一個希望以圖形方式顯示和編輯的模型。為了做到這一點,GEF 提供了可在 Eclipse 工作臺中任何地方使用的查看器(類型為 EditPartViewer )。象 JFace 查看器一樣,GEF 查看器是 SWT 控件上的適配器。但是它們的類似之處僅此而已。GEF 查看器基于模型-視圖-控制器(model-view-controller,MVC)體系結構。

    控制器作為視圖和模型之間的橋梁(請參閱圖 1)。每個控制器(即本文所謂的 EditPart)負責將模型映射到它的視圖,也負責對模型進行更改。EditPart 還觀察模型并更新視圖,以反映模型狀態中的變化。EditPart 是一種對象,用戶將與這種對象進行交互。稍后將更詳細地介紹 EditPart。

    圖 1. 模型-視圖-控制器
    模型-視圖-控制器

    GEF 提供了兩種查看器類型:圖形的和基于樹的。每種查看器都主管一種不同類型的 視圖。圖形查看器使用了在 SWT 畫布(Canvas)上繪制的 圖形(figure)。圖形是在 Draw2D 插件中定義的,該插件是 GEF 的一部分。TreeViewer 將 SWT 樹和 TreeItem 用于其視圖。





    回頁首


    第 1 步. 選定自己的模型

    GEF 對于模型一無所知。任何模型類型都可工作,只要它符合下面描述的特性。

    模型中有什么?

    所有東西都在模型中。模型是唯一會被持久存儲和恢復的東西。您的應用程序應當將所有重要數據都存儲在模型中。在編輯、撤銷和重做的過程中,模型是唯一保持不變的。隨著時間推移,將對圖形和 EditPart 進行垃圾收集處理并重新創建。

    當用戶與 EditPart 交互時,EditPart 并不直接操作模型。而是創建一個封裝了更改的 命令(Command)。命令可用來驗證用戶的交互,并且提供撤銷和重做支持。

    嚴格地說,命令概念上也是模型一部分。它們 本身并不是模型,而是一些方法,模型是由這些方法編輯的。命令用于執行用戶的所有可撤銷的更改。理論上,命令應當只了解模型。它們應當避免引用 EditPart 或圖形。類似地,如果可能,命令應當避免調用用戶界面(例如彈出式對話框)。

    兩個模型的故事

    一個簡單的 GEF 應用程序就是用于繪制圖的編輯器。(這里 只意味著圖片,而不是類圖等)圖可以被建模成某些形狀。一個形狀可能具有位置、顏色等特性,并且可能是多個形狀構成的一組結構。這里沒有什么可驚訝的,并且前述需求也易于維護(請參閱圖 2)。

    圖 2. 一個簡單的模型
    一個簡單的模型

    另一種常見的 GEF 應用程序是 UML 編輯器,例如類圖編輯器。圖中的一段重要信息就是 (x, y) 位置,類就出現在該位置上。根據前一節的介紹,您可能會以為模型必須將一個 描述成具有 xy特性。大多數開發人員都不希望由于無意義的屬性而“污染”其模型。在這類應用程序中,術語“業務”模型可用于指代基本模型,重要語義的詳細信息存儲在基本模型中。而特定于圖的信息存儲在“視圖”模型(它指的是業務模型中某樣東西的“視圖”;在一個圖中可多次查看某個對象)中。有時候這種劃分甚至會反映在工作空間中,其中不同的資源可能被分別用來持久存儲圖和業務模型。甚至可能有多個圖對應于同一個業務模型(請參閱圖 3)。

    圖 3. 劃分成業務模型和視圖模型的模型
    劃分成業務模型和視圖模型的模型

    不管您的模型劃分成了兩個部分,還是劃分成了多個資源,對于 GEF 而言這都是無關緊要的。術語模型用于指代整個應用程序模型。屏幕上的一個對象可能對應于模型中的多個對象。GEF 旨在允許開發人員方便地處理這類映射。

    通知策略

    對視圖進行更新幾乎總是由來自模型的通知而導致的。您的模型必須提供某種通知機制,該機制必須映射到您應用程序中相應的更新。而只讀模型或不能進行通知的模型(例如文件系統或遠程連接)可能是例外。

    通知策略通常是分布式的(每對象)或集中式的(每域)。域通知器了解到對模型中任何對象的每次更改,然后將這些更改向域偵聽器廣播。如果您的應用程序使用了這種通知模型,您可能要為每個查看器添加一個域偵聽器。當該偵聽器接收到更改時,它將查找受影響的 EditPart,然后適當地重新分派該更改。如果您的應用程序使用了分布式通知,那么每個 EditPart 通常都將把自己的偵聽器添加到任何一個影響它的模型對象。





    回頁首


    第 2 步. 定義視圖

    下一步是決定將如何使用來自 Draw2D 插件的圖形顯示您的模型。某些圖形可直接用來顯示模型的某個對象。例如,Label 圖形可用來顯示 Image 和 String。有時候,通過組合多個圖形、布局管理器和/或邊框可以獲得期望的結果。最后,您可能要編寫自己的圖形實現,該實現以特定于您應用程序的方式繪圖。

    有關組合或實現圖形和布局的更多信息可在 Draw2D 開發人員指南中找到,該指南包含在 GEF SDK 中。

    在和 GEF 一起使用 Draw2D 時,通過遵循下列方針,可以使您的項目更便于管理,并且可以更靈活地更改需求:

    • 不要從頭做起。您可以組合所提供的布局管理器以呈現大多數東西。請考慮使用工具欄布局(在垂直或水平方向上)和邊框布局的組合來組合多個圖形。只有在萬不得已時才編寫自己的布局管理器。作為參考,請查看 GEF 中提供的調色板。該調色板是使用 Draw2D 中的許多標準圖形和布局呈現的。

    • 保持 EditPart 和圖形之間“徹底”的分離。如果您的 EditPart 使用了幾個圖形、布局和/或邊框的復合結構,那么請盡量對 EditPart 隱藏詳細信息。讓 EditPart 自己構建所有東西是可能的(但不是個好主意)。不過這樣做并不會導致控制器和視圖之間“徹底”分離。EditPart 非常熟悉圖形結構,因此以類似的 EditPart 重用該結構是不可能的。此外,更改外觀或結構可能會導致意想不到的錯誤。

      替代方法是,您應當編寫自己的 Figure 子類,該子類掩藏了圖形結構的詳細信息。然后定義這個子類最少數量的 API,EditPart(控制器)用這些 API 來更新視圖。這種實踐(稱為 關注分離(separation of concerns))可提高重用機會并使錯誤更少。

    • 不要從圖形引用模型或 EditPart。圖形不應該具有對 EditPart 或模型的訪問權。在某些情形中,EditPart 可能會將自己作為偵聽器添加到圖形,但是只會認為它是偵聽器,而不是 EditPart。這種去耦合(de-coupling)實踐也可以產生更多的重用機會。

    • 使用內容窗格。有時候您擁有一個容器,該容器將包含其它圖形元素,但是您需要在容器四周進行一些裝飾。例如,一個 UML 類通常顯示為框,其頂部標有類名,可能還有一些原型,而底部是為屬性和方法保留的。通過組合多個圖形可以做到這一點。第一個圖形是類的標題框,而另一個圖形被指派為 內容窗格。該圖形將最終包含表示屬性和方法的圖形。稍后在編寫 EditPart 實現時,并不一定要表明應該將內容窗格用作所有子元素的父元素。




    回頁首


    第 3 步. 編寫您的 EditPart - 控制器

    接下來我們將利用控制器(即 EditPart)將模型和視圖聯接起來。該步驟在 GEF 中放置“框架”。所提供的類是抽象的,因此客戶實際上必須編寫代碼。結果證明,生成子類不僅是人們熟悉的方法,而且可能也是將模型映射到視圖最靈活和簡單的方法。

    所提供的用于生成子類的基本實現有三種。對于出現在樹查看器中的 EditPart 使用 AbstractTreeEditPart 。圖形查看器中的繼承 AbstractGraphicalEditPartAbstractConnectionEditPart 。本文將著重討論圖形 EditPart。相同的原理同樣適用于樹查看器。

    EditPart 生命周期

    在編寫您的 EditPart 之前,了解它們來自哪里,以及當不再需要它們時怎樣處理它們,這是有幫助的。每個查看器都配置有一個用于創建 EditPart 的工廠(factory)。當您設置查看器的內容時,通過提供表示該查看器輸入的模型對象,可以做到這一點。輸入通常是最頂部的模型對象,通過該對象可遍歷其它所有對象。然后查看器可以使用自己的工廠來構造用于該輸入對象的 內容 EditPart。之后,查看器中的每個 EditPart 將填充和管理其自己的子 EditPart(和連接 EditPart),當需要新的 EditPart 時,將委派給 EditPart 工廠,直到填充該查看器。當用戶添加新的模型對象時,包含這些對象的 EditPart 將通過構造相應的 EditPart 做出響應。請注意,視圖的構造與 EditPart 的構造是同時進行的。因此,構造每個 EditPart 并將它添加到它的父 EditPart 之后,視圖(不管是圖形還是樹項)也會發生同樣的過程。

    一旦用戶除去與某些 EditPart 對應的模型對象,就丟棄這些 EditPart。如果用戶撤銷了一個刪除操作,那么用于表示被恢復對象而重新創建的 EditPart 與原先的 EditPart 是不同的。這就是為什么 EditPart 不能包含長期信息,以及為什么不應由命令引用的原因。

    您的第一個 EditPart:內容 EditPart

    您編寫的第一個 EditPart 是對應于圖本身的 EditPart。這個 EditPart 稱為查看器的 內容。它對應于模型中最頂部的元素,并且其父元素為查看器的 EditPart(請參閱圖 4)。根通過提供各種圖形層(例如連接層和句柄層等)以及可能會在查看器級別提供的視圖縮放或其它功能,為內容打下基礎。請注意,根的功能不依賴于任何模型對象,GEF 為根提供了幾個現成的實現。

    圖 4. 查看器中的 EditPart
    查看器中的 EditPart

    內容的圖形不是很有趣,并且它通常只是一個空面板,該面板將包含圖的子圖。它的圖形應該為不透明類型(opaque),并且應當利用布局管理器進行初始化,該布局管理器將對圖的子圖進行布局。但是,它將擁有結構。圖的直系子圖是由返回的子模型對象列表確定的。清單 1 顯示了一個樣本內容 EditPart,它創建了一個不透明類型的圖形,后者將使用 XYLayout 定位其子圖。


    清單 1. 內容 EditPart 的初始實現
    												
    														public class DiagramContentsEditPart extends AbstractGraphicalEditPart {
        protected IFigure createFigure() {
            Figure f = new Figure();
            f.setOpaque(true);
            f.setLayoutManager(new XYLayout());
            return f;
        }
    
        protected void createEditPolicies() {
            ...
        }
    
        protected List getModelChildren() {
            return ((MyModelType)getModel()).getDiagramChildren();
        }
    }
    
    												
    										

    要確定圖上的項,需要實現方法 getModelChildren() 。該方法返回子模型對象的列表(例如圖中的節點)。超類將使用這個模型對象列表來創建對應的 EditPart。新創建的 EditPart 被添加到部件的子 EditPart 列表。這樣又會將每個子 EditPart 的圖形添加到示例圖。缺省情況下,將返回一個空的列表,這表明沒有子對象。

    其它圖形 EditPart

    其余的 EditPart(表示圖中的項)可能擁有要以圖形方式顯示的數據。它們可能還擁有自己的結構,例如連接或自己的子 EditPart。許多 GEF 應用程序利用由標簽注明的圖標之間的連接來描述這些圖標。讓我們假定您的 EditPart 將使用 Label 作為它的圖形,并且您的模型提供了名稱、圖標以及與標簽之間的連接。清單 2 顯示了實現這種類型 EditPart 的第一次嘗試。


    清單 2. “節點”EditPart 的初始實現
    												
    														public class MyNodeEditPart extends AbstractGraphicalEditPart {
        protected IFigure createFigure() {
            return new Label();
        }
        protected void createEditPolicies() {
            ...
        }
        protected List getModelSourceConnections() {
            MyModel node = (MyModel)getModel();
            return node.getOutgoingConnections();
        }
        protected List getModelTargetConnections() {
            MyModel node = (MyModel)getModel();
            return node.getIncomingConnections();
        }
        protected void refreshVisuals() {
            MyModel node = (MyModel)getModel();
            Label label = (Label)getFigure();
            label.setText(node.getName());
            label.setIcon(node.getIcon());
    
            Rectangle r = new Rectangle(node.x, node.y, -1, -1);
            ((GraphicalEditPart) getParent()).setLayoutConstraint(this, label, r);
        }
    }
    
    												
    										

    這里覆蓋了一個新方法 refreshVisuals() 。當需要利用來自模型的數據更新圖形時,就調用該方法。在本案例中,模型的名稱和圖標被反映在標簽中。但更為重要的是,該標簽是通過將其布局約束傳遞給父元素來定位的。在內容 EditPart 中,我們使用了 XY 布局管理器。該布局使用 Rectangle 約束來確定在何處放置子圖形。寬和高的值為“-1”,表明應當為該圖提供理想的大小。

    技巧 #1

    決不要使用 setBounds(...) 方法來放置圖形。使用諸如 XYLayout 之類的布局管理器確保會正確地更新滾動條。另外,XYLayout 還處理將相對約束轉換成絕對位置的工作,并且可用它來將圖形自動調整為理想的大?。〒Q而言之,如果約束的寬和高為 -1)。

    方法 refreshVisuals() 僅在 EditPart 初始化的過程中調用一次,并且決不會被再次調用。在響應模型通知時,應用程序負責根據需要再次調用 refreshVisuals() 以更新圖形。要改進性能,您可能希望將每個模型屬性的代碼分解成其自己的方法(或者是一個帶有“開關(switch)”的方法)。這樣,當模型發出通知時,可以運行最少的代碼以便只刷新那些發生更改的內容。

    另一個有趣的區別是連接支持的代碼。與 getModelChildren() 類似, getModelSourceConnections()getModelTargetConnections() 應當返回表示節點之間連接的模型對象。超類在必要時創建對應的 EditPart,并將它們添加到源和目標連接 EditPart 列表。請注意,連接是由每端的節點引用的,而其 EditPart 只需創建一次。GEF 確保只創建一次連接,該工作是通過首先檢查查看器中是否已經存在連接來完成的。





    回頁首


    建立連接

    編寫連接 EditPart 實現沒有太大的區別。首先生成 AbstractConnectionEditPart 的子類。跟前面一樣,可以實現 refreshVisuals() ,以將屬性從模型映射到圖形。連接可能還擁有約束,盡管這些約束與前面的約束略有不同。這里,連接路由器使用約束來使連接轉向(bend)。此外,連接 EditPart 的圖形必須是 Draw2D Connection ,它引入了另一個需求:連接錨(connection anchor)。

    連接必須由 ConnectionAnchor “錨定”在兩端。因此,必須在連接 EditPart 中或在節點實現中表明使用哪些錨。缺省情況下,GEF 假定節點 EditPart 將通過實現 NodeEditPart 接口而提供錨。這樣假定的一個原因是,錨的選擇取決于各端上的節點正在使用的圖形。連接 EditPart 不應了解節點正在使用的圖形的任何內容。另一個原因是,當用戶創建連接時,連接 EditPart 是不存在的,因此節點必須能夠自己顯示反饋。作為清單 2 的延續,我們在清單 3 中添加了必要的錨支持。


    清單 3. 將錨支持添加到“節點”EditPart
    												
    														public class MyNodeEditPart
        extends AbstractGraphicalEditPart
        implements NodeEditPart
    {
        ...
        public ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart connection) {
            return new ChopboxAnchor(getFigure());
        }
        public ConnectionAnchor getSourceConnectionAnchor(Request request) {
            return new ChopboxAnchor(getFigure());
        }
        public ConnectionAnchor getTargetConnectionAnchor(ConnectionEditPart connection) {
            return new ChopboxAnchor(getFigure());
        }
        public ConnectionAnchor getTargetConnectionAnchor(Request request) {
            return new ChopboxAnchor(getFigure());
        }
    
        ...
    }
    
    												
    										

    技巧 #2

    別忘記真正實現 NodeEditPart 接口。否則您的方法將永遠不會被調用。

    以連接(connection)為參數的方法是對現有連接 EditPart 設置錨時使用的方法。其它兩個方法以請求(request)作為參數。這些方法是用戶創建新連接時的編輯過程中使用的。對于本示例,所有情形都將返回 chopbox 錨。chopbox 錨只查找線與節點圖形的邊框相交的點。

    實現連接 EditPart 是比較簡單的。請注意,甚至無需創建圖形,因為缺省的 PolylineConnection 創建適合于大多數場合(請參閱清單 4)。


    清單 4. 初始的連接 EditPart 實現
    												
    														public class MyConnectionEditPart extends AbstractConnectionEditPart {
        protected void createEditPolicies() {
            ...
        }
    
        protected void refreshVisuals() {
            PolylineConnection figure = (PolylineConnection)getFigure();
            MyConnection connx = (MyConnection)getModel();
            figure.setForegroundColor(MagicHelper.getConnectionColor(connx));
            figure.setRoutingConstraint(MagicHelper.getConnectionBendpoints(connx));
        }
    }
    
    												
    										

    技巧 #3

    最重要的是了解何時使用以及何時不使用 ConnectionEditPart。當用戶可以選擇某些東西并可與之進行交互的時候,就使用連接 EditPart。它可能與模型中的某個對象直接相關,并且通??捎勺约簞h除。

    如果您只是擁有一個需要繪制直線的節點或容器,那么只須用圖形的 paint 方法繪制直線,或者組合一個圖形,該圖形包含 Polyline 圖形。

    連接始終都必須擁有源和目標。如果您需要一個連接,該連接可以在沒有源或沒有目標的情況下存在,那么比較好的方法是只繼承 AbstractGraphicalEditPart ,并使用連接圖形。

    偵聽模型

    創建 EditPart 之后,它應該開始偵聽來自模型的更改通知。由于 GEF 是與模型無關的,因此所有應用程序都必須添加自己的偵聽器,并處理產生的通知。接收到通知時,處理程序可以調用某個提供的方法來強制進行一次刷新。例如,如果刪除了一個子模型對象,那么調用 refreshChildren() 將導致對應的 EditPart 及其圖形被除去。對于簡單的屬性更改,可以使用 refreshVisuals() 。正如我們前面提及的,可將該方法分解成幾個部分,從而避免沒有必要地更新每個顯示的屬性。

    添加偵聽器但卻忘記除去它們是導致內存泄漏的常見原因。出于這個原因,添加和除去偵聽器的地方應該在 API 中清晰地注明。您的 EditPart 必須繼承 activate() ,以便添加稍后必須除去的任何偵聽器。通過繼承 deactivate() 可除去那些相同的偵聽器。清單 5 顯示了向節點 EditPart 實現添加的模型通知內容。


    清單 5. 偵聽“節點”EditPart 中的模型更改
    												
    														public class MyNodeEditPart
    extends AbstractGraphicalEditPart
        implements NodeEditPart, ModelListener
    {
        ...
    
        public void activate() {
            super.activate();
            ((MyModel)getModel()).addModelListener(this);
        }
    
        public void deactivate() {
            ((MyModel)getModel()).removeModelListener(this);
            super.deactivate();
        }
    
        public void modelChanged(ModelEvent event) {
            if (event.getChange().equals("outgoingConnections"))
                refreshSourceConnections();
            else if (event.getChange().equals("incomingConnections"))
                refreshTargetConnections();
            else if (event.getChange().equals("icon")
              || event.getChange().equals("name"))
                refreshVisuals();
        }
    
        ...
    }
    
    												
    										

    編輯模型

    到目前為止,我們已經講解了如何創建 EditPart,它們如何創建自己的可視圖(visual)以及當模型發生變化時它們如何自我更新。除此之外,EditPart 也是對模型進行更改的主要參與者。當命令的請求被發送給 EditPart 時就會發生這種情況。請求還用來要求 EditPart 顯示諸如在鼠標拖動期間發生的反饋。EditPart 支持、阻止或忽略給定的請求。所支持或阻止的請求類型決定了 EditPart 的行為。

    到目前為止,側重點都是將模型的結構和特性映射到視圖。結果表明,這基本上是您在 EditPart 類自身中所做的所有工作。其行為是由一組名為 EditPolicies 的可插入的助手類決定的。在所提供的示例中,我們忽略了方法 createEditPolicies() 。一旦您實現該方法,您就幾乎已經完成了您的 EditPart。當然,您仍需要提供編輯策略,該策略知道如何修改您應用程序的模型。

    因為編輯行為是可插入的,所以在開發各種 EditPart 實現時,可以根據將模型映射到視圖和處理模型更新這種任務,來創建類層次結構。





    回頁首


    第 4 步. 將所有內容組合在一起

    現在,您已經完成了以圖形方式顯示您的模型所需的所有部分。對于最后的組裝,我們將使用 IEditorPart 。但是,也可以在視圖、對話框或者可以放置控件的幾乎任何地方使用 GEF 的查看器。對于本步驟,您必須擁有自己的 UI 插件,它將為正在打開的資源定義編輯器和文件擴展名??稍谕粋€插件或一個不同的插件中定義您的模型。您還需要一個預填充的模型,因為目前還沒有編輯功能。

    提供樣本模型數據的方法有幾種。對于本示例而言,當編輯器打開時,我們將在代碼中創建模型,從而忽略了文件的實際內容。要做到這一點,我們假定已經存在一個測試工廠?;蛘?,您可以創建一個示例向導,該向導用數據對資源進行預填充(普通向導只創建空圖)。最后,您可以利用文本編輯器以手工方式編寫文檔的內容。

    既然您有了樣本模型,那么讓我們創建將顯示模型的編輯器部件。有一種快速的方法,就是生成子類或復制 GEF 的 GraphicalEditor 。該類創建 ScrollingGraphicalViewer 的一個實例,并且構造一個畫布來充當編輯器的控件。它是一個很方便的類,用來幫助您開始使用 GEF;一個可以正確工作的 Eclipse 編輯器需要考慮很多其它事情,例如不利的團隊環境(pessimistic team environment)和要刪除或移動資源等。

    清單 6 顯示了一個樣本編輯器實現。有幾個必須實現的抽象方法。出于本文所討論范圍的限制,我們將忽略模型持久性和標記。要讓您的圖出現在圖形查看器中,您必須做兩件事情。首先,利用自己的 EditPart 工廠配置查看器,以從第 3 步構造 EditPart。然后,將圖模型對象傳遞給查看器。


    清單 6. 實現您的編輯器部件(Editor Part)
    												
    														public class MyEditor extends GraphicalEditor {
        public MyEditor() {
            setEditDomain(new DefaultEditDomain(this));
        }
    
        protected void configureGraphicalViewer() {
            super.configureGraphicalViewer(); //Sets the viewer's background to System "white"
            getGraphicalViewer().setEditPartFactory(new MyGraphicalEditpartFactory());
        }
    
        protected void initializeGraphicalViewer() {
            getGraphicalViewer().setContents(MagicHelper.constructSampleDiagram());
        }
        public void doSave(IProgressMonitor monitor) {
            ...
        }
        public void doSaveAs() {
            ...
        }
        public void gotoMarker(IMarker marker) {
            ...
        }
        public boolean isDirty() {
            ...
        }
        public boolean isSaveAsAllowed() {
            ...
        }
    }
    
    												
    										





    回頁首


    接下來的步驟

    我們已經經歷了從僅擁有一個模型到在圖形編輯器中顯示該模型的全過程。但是我們只打下了基礎。我們簡要提及了編輯策略。通過閱讀與 GEF SDK 一起提供的開發人員文檔,可以獲得有關編輯策略的更多信息。還可從 GEF 的主頁(請參閱文章結尾的 參考資料)獲得一個示例,該示例演示了如何使用各種編輯策略類型。

    GEF 還提供了一個調色板。該調色板顯示了一組工具,用于在圖中創建對象。用戶可以激活這些工具,或者使用本機拖放直接從該調色板拖動項。它還支持讓用戶定制內容。

    在 GEF 中還可以使用幾個 JFace 操作。應用程序可以在菜單、工具欄或上下文菜單中使用諸如撤銷、對齊和刪除之類的操作。

    最后,您的應用程序應當支持大綱(outline)視圖和特性(properties)視圖。大綱視圖用于導航和有限的編輯用途。GEF 的 TreeViewer 和/或概述(overview)窗口可以在這里使用。特性表(property sheet)允許用戶查看和編輯任何當前選定項的詳細特性。

    為了顯示所選擇的項并允許用戶進行更改,您必須將編輯策略添加到 EditPart。請參閱 GEF 主頁上的示例,并參閱與 GEF SDK 一起提供的開發人員文檔。

    有關 GEF 和 Eclipse 工作臺提供的其它功能的詳細信息不在本文的討論范疇之內,但是您可能有興趣對它們稍做了解:

    • 調色板。該工具的調色板是用于在圖中創建新對象的 實際方法。GEF 包含了一個功能豐富的調色板,它支持拖放、多繪圖程序和布局設置,如果應用程序希望,它甚至可支持讓用戶定制內容。
    • 操作欄。編輯器(Editor)和視圖(View)可以為工具欄、菜單和上下文菜單提供操作(Action)。GEF 提供了幾個可重用的操作實現,但是將它們顯示在什么地方取決于應用程序。
    • 特性表。特性表可用于顯示所選項特性的詳細信息。GEF 允許您在 EditPart 上或在模型中添加特性表支持。
    • 大綱。大綱視圖通常用于顯示圖的結構化表示,但是一般來說,它可用于任何工作。GEF 的 TreeViewer 通常在大綱視圖中使用。




    回頁首


    參考資料





    回頁首


    關于作者

    Randy Hudson 是北卡羅來納州 Research Triangle Park 的 IBM 軟件工程師。作為圖形編輯框架(Graphical Editing Framework,GEF)的技術領導,他幫助將這個曾經是內部的項目轉變成了開放源碼技術。他目前的工作側重于可用性、圖形編輯、圖形布局和邊緣路由(edge routing)??梢酝ㄟ^ buchu at nc.rr.com與 Randy 聯系。


    from: http://www-128.ibm.com/developerworks/cn/linux/opensource/os-gef/index.html

    posted on 2006-09-04 10:57 weidagang2046 閱讀(317) 評論(0)  編輯  收藏 所屬分類: Java

    主站蜘蛛池模板: 亚洲AV午夜成人片| 亚洲av永久中文无码精品| 免费人成在线观看69式小视频| 亚洲综合丁香婷婷六月香| 国产一区在线观看免费| 在线人成免费视频69国产| 亚洲精品123区在线观看| 亚洲综合色视频在线观看| 50岁老女人的毛片免费观看| 久久久久久亚洲精品无码| 亚洲色欲久久久综合网| 女人18毛片免费观看| 丝袜足液精子免费视频| 亚洲熟伦熟女专区hd高清| 国产亚洲精品岁国产微拍精品| aa级一级天堂片免费观看| 中文字幕无线码免费人妻| 日本亚洲色大成网站www久久 | 国产精品福利片免费看| 亚洲乱人伦精品图片| 在线观看亚洲成人| 最近2019中文字幕免费看最新 | 国产精品免费无遮挡无码永久视频| 亚洲人精品亚洲人成在线| 日日噜噜噜噜夜夜爽亚洲精品| 毛片免费观看视频| 一级成人a毛片免费播放| 黄色a三级免费看| 亚洲中文字幕久久无码| 亚洲欧洲国产精品你懂的| 亚洲日韩人妻第一页| 最近免费中文字幕视频高清在线看| 国内永久免费crm系统z在线| 亚洲第一se情网站| 亚洲人成网男女大片在线播放| 久久91亚洲人成电影网站| 亚洲成av人在片观看| 毛片a级毛片免费观看免下载| 日韩精品极品视频在线观看免费| jizz中国免费| 日本永久免费a∨在线视频|