`

[zt]使用图形编辑框架创建基于 Eclipse 的应用程序

阅读更多

FROM:http://www-128.ibm.com/developerworks/cn/linux/opensource/os-gef/


2003 年 10 月 10 日

本文描述了使用图形编辑框架(Graphical Editing Framework,GEF)创建一个基于 Eclipse 的应用程序所涉及的初始步骤。GEF 被用来构建各种用于 Eclipse 的应用程序,包括状态图、活动图、类图、用于 AWT、Swing 和 SWT 的 GUI 构建器以及过程流编辑器。Eclipse 和 GEF 都是开放源码技术。二者也都包含在 IBM 的 WebSphere Studio 工作台中。
本文为您从头到尾地介绍了使用 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) 位置,类就出现在该位置上。根据前一节的介绍,您可能会以为模型必须将一个 类描述成具有 x和 y特性。大多数开发人员都不希望由于无意义的属性而“污染”其模型。在这类应用程序中,术语“业务”模型可用于指代基本模型,重要语义的详细信息存储在基本模型中。而特定于图的信息存储在“视图”模型(它指的是业务模型中某样东西的“视图”;在一个图中可多次查看某个对象)中。有时候这种划分甚至会反映在工作空间中,其中不同的资源可能被分别用来持久存储图和业务模型。甚至可能有多个图对应于同一个业务模型(请参阅图 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 。图形查看器中的继承 AbstractGraphicalEditPart 和 AbstractConnectionEditPart 。本文将着重讨论图形 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 的初始实现
 

java 代码
  1. public class DiagramContentsEditPart extends AbstractGraphicalEditPart {   
  2.     protected IFigure createFigure() {   
  3.         Figure f = new Figure();   
  4.         f.setOpaque(true);   
  5.         f.setLayoutManager(new XYLayout());   
  6.         return f;   
  7.     }   
  8.     protected void createEditPolicies() {   
  9.         ...   
  10.     }   
  11.     protected List getModelChildren() {   
  12.         return ((MyModelType)getModel()).getDiagramChildren();   
  13.     }   
  14. }   


要确定图上的项,需要实现方法 getModelChildren() 。该方法返回子模型对象的列表(例如图中的节点)。超类将使用这个模型对象列表来创建对应的 EditPart。新创建的 EditPart 被添加到部件的子 EditPart 列表。这样又会将每个子 EditPart 的图形添加到示例图。缺省情况下,将返回一个空的列表,这表明没有子对象。

其它图形 EditPart

其余的 EditPart(表示图中的项)可能拥有要以图形方式显示的数据。它们可能还拥有自己的结构,例如连接或自己的子 EditPart。许多 GEF 应用程序利用由标签注明的图标之间的连接来描述这些图标。让我们假定您的 EditPart 将使用 Label 作为它的图形,并且您的模型提供了名称、图标以及与标签之间的连接。清单 2 显示了实现这种类型 EditPart 的第一次尝试。

 

清单 2. “节点”EditPart 的初始实现

java 代码
  1. public class MyNodeEditPart extends AbstractGraphicalEditPart {   
  2.     protected IFigure createFigure() {   
  3.         return new Label();   
  4.     }   
  5.     protected void createEditPolicies() {   
  6.         ...   
  7.     }   
  8.     protected List getModelSourceConnections() {   
  9.         MyModel node = (MyModel)getModel();   
  10.         return node.getOutgoingConnections();   
  11.     }   
  12.     protected List getModelTargetConnections() {   
  13.         MyModel node = (MyModel)getModel();   
  14.         return node.getIncomingConnections();   
  15.     }   
  16.     protected void refreshVisuals() {   
  17.         MyModel node = (MyModel)getModel();   
  18.         Label label = (Label)getFigure();   
  19.         label.setText(node.getName());   
  20.         label.setIcon(node.getIcon());   
  21.         Rectangle r = new Rectangle(node.x, node.y, -1, -1);   
  22.         ((GraphicalEditPart) getParent()).setLayoutConstraint(this, label, r);   
  23.     }   
  24. }   

 


这里覆盖了一个新方法 refreshVisuals() 。当需要利用来自模型的数据更新图形时,就调用该方法。在本案例中,模型的名称和图标被反映在标签中。但更为重要的是,该标签是通过将其布局约束传递给父元素来定位的。在内容 EditPart 中,我们使用了 XY 布局管理器。该布局使用 Rectangle 约束来确定在何处放置子图形。宽和高的值为“-1”,表明应当为该图提供理想的大小。

 

技巧 #1 决不要使用 setBounds(...) 方法来放置图形。使用诸如 XYLayout 之类的布局管理器确保会正确地更新滚动条。另外,XYLayout 还处理将相对约束转换成绝对位置的工作,并且可用它来将图形自动调整为理想的大小(换而言之,如果约束的宽和高为 -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

java 代码
  1. public class MyNodeEditPart   
  2.     extends AbstractGraphicalEditPart   
  3.     implements NodeEditPart   
  4. {   
  5.     ...   
  6.     public ConnectionAnchor getSourceConnectionAnchor(ConnectionEditPart connection) {   
  7.         return new ChopboxAnchor(getFigure());   
  8.     }   
  9.     public ConnectionAnchor getSourceConnectionAnchor(Request request) {   
  10.         return new ChopboxAnchor(getFigure());   
  11.     }   
  12.     public ConnectionAnchor getTargetConnectionAnchor(ConnectionEditPart connection) {   
  13.         return new ChopboxAnchor(getFigure());   
  14.     }   
  15.     public ConnectionAnchor getTargetConnectionAnchor(Request request) {   
  16.         return new ChopboxAnchor(getFigure());   
  17.     }   
  18.     ...   
  19. }   

 技巧 #2 别忘记真正实现 NodeEditPart 接口。否则您的方法将永远不会被调用。

以连接(connection)为参数的方法是对现有连接 EditPart 设置锚时使用的方法。其它两个方法以请求(request)作为参数。这些方法是用户创建新连接时的编辑过程中使用的。对于本示例,所有情形都将返回 chopbox 锚。chopbox 锚只查找线与节点图形的边框相交的点。

 

实现连接 EditPart 是比较简单的。请注意,甚至无需创建图形,因为缺省的 PolylineConnection 创建适合于大多数场合(请参阅清单 4)。

清单 4. 初始的连接 EditPart 实现

 java 代码

  1. public class MyConnectionEditPart extends AbstractConnectionEditPart {   
  2.     protected void createEditPolicies() {   
  3.         ...   
  4.     }   
  5.     protected void refreshVisuals() {   
  6.         PolylineConnection figure = (PolylineConnection)getFigure();   
  7.         MyConnection connx = (MyConnection)getModel();   
  8.         figure.setForegroundColor(MagicHelper.getConnectionColor(connx));   
  9.         figure.setRoutingConstraint(MagicHelper.getConnectionBendpoints(connx));   
  10.     }   
  11. }   

 

技巧 #3 最重要的是了解何时使用以及何时不使用 ConnectionEditPart。当用户可以选择某些东西并可与之进行交互的时候,就使用连接 EditPart。它可能与模型中的某个对象直接相关,并且通常可由自己删除。

如果您只是拥有一个需要绘制直线的节点或容器,那么只须用图形的 paint 方法绘制直线,或者组合一个图形,该图形包含 Polyline 图形。

连接始终都必须拥有源和目标。如果您需要一个连接,该连接可以在没有源或没有目标的情况下存在,那么比较好的方法是只继承 AbstractGraphicalEditPart ,并使用连接图形。

 

侦听模型

创建 EditPart 之后,它应该开始侦听来自模型的更改通知。由于 GEF 是与模型无关的,因此所有应用程序都必须添加自己的侦听器,并处理产生的通知。接收到通知时,处理程序可以调用某个提供的方法来强制进行一次刷新。例如,如果删除了一个子模型对象,那么调用 refreshChildren() 将导致对应的 EditPart 及其图形被除去。对于简单的属性更改,可以使用 refreshVisuals() 。正如我们前面提及的,可将该方法分解成几个部分,从而避免没有必要地更新每个显示的属性。

添加侦听器但却忘记除去它们是导致内存泄漏的常见原因。出于这个原因,添加和除去侦听器的地方应该在 API 中清晰地注明。您的 EditPart 必须继承 activate() ,以便添加稍后必须除去的任何侦听器。通过继承 deactivate() 可除去那些相同的侦听器。清单 5 显示了向节点 EditPart 实现添加的模型通知内容。

 

清单 5. 侦听“节点”EditPart 中的模型更改

 

  1. public class MyNodeEditPart   
  2. extends AbstractGraphicalEditPart   
  3.     implements NodeEditPart, ModelListener   
  4. {   
  5.     ...   
  6.     public void activate() {   
  7.         super.activate();   
  8.         ((MyModel)getModel()).addModelListener(this);   
  9.     }   
  10.     public void deactivate() {   
  11.         ((MyModel)getModel()).removeModelListener(this);   
  12.         super.deactivate();   
  13.     }   
  14.     public void modelChanged(ModelEvent event) {   
  15.         if (event.getChange().equals("outgoingConnections"))   
  16.             refreshSourceConnections();   
  17.         else if (event.getChange().equals("incomingConnections"))   
  18.             refreshTargetConnections();   
  19.         else if (event.getChange().equals("icon")   
  20.           || event.getChange().equals("name"))   
  21.             refreshVisuals();   
  22.     }   
  23.     ...   
  24. }   
  25.    

 


编辑模型

到目前为止,我们已经讲解了如何创建 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)

java 代码
  1. public class MyEditor extends GraphicalEditor {   
  2.     public MyEditor() {   
  3.         setEditDomain(new DefaultEditDomain(this));   
  4.     }   
  5.     protected void configureGraphicalViewer() {   
  6.         super.configureGraphicalViewer(); //Sets the viewer's background to System "white"   
  7.         getGraphicalViewer().setEditPartFactory(new MyGraphicalEditpartFactory());   
  8.     }   
  9.     protected void initializeGraphicalViewer() {   
  10.         getGraphicalViewer().setContents(MagicHelper.constructSampleDiagram());   
  11.     }   
  12.     public void doSave(IProgressMonitor monitor) {   
  13.         ...   
  14.     }   
  15.     public void doSaveAs() {   
  16.         ...   
  17.     }   
  18.     public void gotoMarker(IMarker marker) {   
  19.         ...   
  20.     }   
  21.     public boolean isDirty() {   
  22.         ...   
  23.     }   
  24.     public boolean isSaveAsAllowed() {   
  25.         ...   
  26.     }   
  27. }   
  28.    

 

接下来的步骤

我们已经经历了从仅拥有一个模型到在图形编辑器中显示该模型的全过程。但是我们只打下了基础。我们简要提及了编辑策略。通过阅读与 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 通常在大纲视图中使用。


 参考资料

  • 您可以参阅本文在 developerWorks 全球站点上的 英文原文.

  • 请在 GEF 主页上下载插件并查找有关 GEF 的其它信息。



  • GEF 新闻组是查找答案和进行提问的极佳场所。



  • Eclipse 项目主管着 Eclipse 工作台、GEF 和其它开放源码技术。



  • 请在 developerWorks上浏览 针对开发人员的其它 Eclipse 文章
  •  

    分享到:
    评论

    相关推荐

      zt411-zt421-ug-zhcn_ZT411/ZT421_斑马打印机手册_

      斑马打印机ZT411和ZT421是工业级条码和标签打印机,广泛应用于制造业、物流、零售业等对打印质量和效率有高要求的领域。这两款打印机以其出色的性能、耐用性和易用性赢得了用户的信赖。这份中文手册详细地介绍了ZT...

      Zebra ZT230 条码打印机驱动

      斑马(Zebra)ZT230条码打印机是一款广泛应用在工业环境中的高效设备,其驱动程序是确保打印机正常工作的重要组成部分。本驱动程序专为Zebra的ZT210、ZT220及ZT230系列打印机设计,提供了全面的功能支持,以实现高...

      eclipse+jboss+jsp.rar

      标题 "eclipse+jboss+jsp.rar" 涉及到的是一个关于如何在Eclipse集成开发环境中配置和使用JBoss应用服务器以及开发JSP应用程序的综合教程。这个压缩包包含了多个指南和步骤文档,帮助开发者了解和实践相关配置。 ...

      ZT213/ZT213LEEA规格书V2.10-低功耗RS232多通道USB收发器/驱动器芯片手册

      ZT213/ZT213LEEA是一款专为低功耗应用设计的RS232多通道USB收发器和驱动器芯片,广泛应用于数据通信、工业控制、物联网设备等领域。本文将深入探讨其规格参数、功能特点、选型指南及应用实例,帮助读者全面了解这款...

      证通ZT598金属键盘开发资料.rar

      证通ZT598是一款专门用于金融、安防等领域,具备高安全性和可靠性的金属键盘设备。这款设备的开发资料包含在"证通ZT598金属键盘开发资料.rar"压缩包中,主要适用于那些进行嵌入式系统开发的工程师。在深入探讨其开发...

      ZT19600/25/50端头液压支架的应用

      在冀中能源峰峰集团新屯矿的应用实践中,ZT19600/25/50端头液压支架的使用使得生产作业更加安全、高效和有序。 5. 设备参数: 文件中提到了多种型号的液压支架以及其它矿业设备,例如:ZT19600/25/50、ZF3200/16/...

      为Delphi应用增加脚本支持(ZT)

      在IT行业中,为应用程序添加脚本支持是一种常见的增强软件功能和灵活性的方式。Delphi作为一款强大的Windows应用程序开发工具,提供了丰富的功能和库,使得开发者能够为自己的应用集成脚本引擎,使得用户或开发者...

      斑马zt410中文库

      斑马(Zebra)ZT410是一款先进的桌面级条码打印机,被广泛应用于物流、零售、医疗、制造业等多个行业。这款打印机以其高效、耐用和易于操作的特点深受用户喜爱。"斑马zt410中文库"指的是为ZT410打印机特别设计的中文...

      RS485通信芯片zt13085e的原理图库和PCB库

      总的来说,ZT13085E作为一款RS485通信芯片,是构建工业通信网络的重要组成部分,其原理图库和PCB库的创建和使用对于电路设计者来说是必不可少的,能够提高设计效率并确保硬件的正确连接。在实际应用中,理解其工作...

      斑马打印机(ZT210).docx

      斑马打印机ZT210是一款专业的工业级条形码和标签打印机,广泛应用于物流、零售、医疗等行业的标签制作。以下是对如何设置和使用斑马ZT210打印机的详细步骤: 首先,我们需要安装电脑驱动。双击下载好的驱动程序文件...

      用GDB调试程序(zt).pdf

      5. **运行至断点**:使用`run`(或`r`)命令运行程序直至遇到第一个断点,或者使用`continue`(或`c`)命令从当前断点继续执行至下一个断点。 6. **检查状态**:在程序暂停时,使用`print`(或`p`)命令查看变量值...

      ZK-ZT2使用手册(1).pdf

      本文档是关于ZK-ZT2多功能直流电机调速器的使用手册。手册详细介绍了该调速器的功能、参数指标、接口说明及控制模式等内容。以下是手册中的关键知识点总结: 1. 产品简介 ZK-ZT2调速器支持四种运行模式:手动(人工...

      免费电影程序免费电影程序

      综合以上分析,这个免费电影程序2.0很可能是一个基于ASP开发的Web应用程序,集成了电影搜索、播放、评论和安装等功能。它使用MaxCMS作为内容管理框架,允许用户方便地浏览和观看电影,同时提供了一个互动平台让用户...

      website:ZT react 应用程序的代码库

      【标题】"ZT react 应用程序的代码库"涉及的是使用React技术构建的Web应用程序,特别是与ZT相关的项目。React是Facebook开发的一个开源JavaScript库,用于构建用户界面,尤其是单页应用。它专注于视图层,是构建可...

      斑马打印机ZT210用户指南

      "斑马打印机ZT210用户指南" 本用户指南旨在为Zebra ZT210/ZT220/ZT230打印机的用户提供操作和维护指南,该设备是一种工业级的条码打印机,具有高速打印、高速处理和高质量打印输出等特点。 版权信息 本手册的版权...

      斑马ZebraZT210打印样例

      斑马Zebra ZT210是一款广泛应用在零售、物流、医疗等行业的桌面级条码打印机,以其稳定性和高效性能而受到青睐。本教程将详细讲解如何利用ZT210打印机及其驱动程序,通过C#编程语言实现自定义打印内容。 首先,我们...

      STM开发板列程包对学习STM32F103ZT6

      STM32F103ZT6是一款基于ARM Cortex-M3内核的微控制器,广泛应用于嵌入式系统设计,特别是在工业控制、消费电子和物联网(IoT)设备中。这款芯片具有丰富的功能集,包括多个定时器、串行通信接口、GPIO、ADC和DMA等。...

    Global site tag (gtag.js) - Google Analytics