`

(转载)使用图形编辑框架创建基于 Eclipse 的应用程序

 
阅读更多

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

倾向于使用图形的 Eclipse 开发人员如何开始使用 GEF 和其他选项

Randy Hudson, 软件开发人员, IBM 
Chris Aniszczyk, 软件工程师, IBM 

 

简介: 了解使用图形编辑框架(Graphical Editing Framework,GEF)创建基于 Eclipse 的应用程序涉及的最初步骤。此外,介绍了目前在 Eclipse 中引导创建图形编辑器过程使用的选项。

发布日期: 2007 年 7 月 02 日
级别: 中级
访问情况 : 3498 次浏览
评论: 0 (查看 | 添加评论 - 登录) <!-- Rating_Area_Begin -->

平均分 1 星 共 1 个评分 平均分 (1个评分)
为本文评分

编辑注:这篇文章最初由 Randy Hudson 于 2003 年 7 月撰写的,Chris Aniszczyk 于 2007 年 3 月更新。

本文将介绍使用图形编辑框架(Graphical Editing Framework,GEF)的步骤。我们不是完整地完成每个步骤,而是将使用您的应用程序模型的子集,并先使该子集工作。例如,开始我们可能会忽略连接,或者只注意应用程序中图形元素类型的子集。接下来,了解其他可向应用程序添加图形编辑功能的技术。过去,独立 GEF 曾是在 Eclipse 中进行图形编辑的惟一选择,但是这种情况随着 Eclipse 的发展而发生了改变。

GEF 概述

GEF 将假定您具有想用图形显示和编辑的模型。为此,GEF 将提供可以在 Eclipse 工作区的任意位置使用的查看器(EditPartViewer 类型)。类似于 JFace 查看器,GEF 查看器是用于 SWT Control 的适配器。但是相似性仅止于此。GEF 查看器是基于模型-视图-控制器(Model-View-Controller,MVC)架构的。

控制器是连接视图与模型的桥梁(参见图 1)。每个控制器,即本文所谓的 EditPart,负责将模型映射到视图并对模型进行更改。EditPart 还将监视模型并更新视图以反映模型状态中的更改。EditPart 是与用户进行交互的对象。稍后将详细介绍 EditPart


图 1. 模型-视图-控制器
模型-视图-控制器

GEF 提供了两种查看器类型:图形查看器和基于树的查看器。每种查看器类型将托管不同类型的视图。图形查看器将使用在 SWT Canvas 上绘制的图形。图形都是在 GEF 附带的 Draw2D 插件中定义的。TreeViewer 将 SWT TreeTreeItem 用于其视图。

步骤 1:引入您自己的模型

GEF 对模型一无所知。任何模型类型应当都能运行,只要它满足下面描述的属性。

模型中有什么?

一切尽在模型中。模型是惟一被存储和恢复的内容。应用程序应当把所有重要数据存储到模型中。在编辑、撤消和重做的过程中,模型是惟一保持不变的。图形和 EditPart 在经过一段时间后将被回收和重建。

当用户与 EditPart 进行交互时,模型不是由 EditPart 直接处理的。相反,将创建 Command 以封装更改。Command 可用于验证用户的交互,并可用于提供撤消和重做支持。

严格来说,Command 也属于模型的概念范畴。它们本质上不是模型,但是是编辑模型的方法。命令用于执行所有用户的撤消更改。在理想的情况下,命令应当只知道模型。它们应当避免引用 EditPart 或图形。类似地,只要可能,命令应当避免调用用户界面(例如弹出式对话框)。

两个模型的故事

简单的 GEF 应用程序是用于绘制图形的编辑器。(在这里,图形 仅指图片,而不是类图)。图形可以被模块化为一些形状(shape)。形状可能拥有位置、颜色等属性,并且可能是多个形状构成的一组结构。这里没有什么可惊讶的,并且以前的要求也很易于维护。


图 2. 简单模型
简单模型

另一个常用 GEF 应用程序是 UML 编辑器,例如类图编辑器。图中的一项重要信息是显示类的 (x, y) 位置。您可能会以为模型必须将一个类描述成具有 x 和 y 特性。大多数开发人员都希望避免用毫无意义的属性来破坏他们的模型。在此类应用程序中,术语业务模型 可用于指代存储重要的语义详细信息 的基本模型。同时,图的特定信息存储在视图模型(即业务模型中的某个视图;可以在一个图中查看多次的对象)中。有时分割甚至还反映在工作区中,各种资源可用于分别保留图和业务模型。同一个业务模型甚至可以有若干个图(参见图 3)。视图模型的常用术语是符号模型


图 3. 一个模型分割为业务模型和视图模型
一个模型分割为业务模型和视图模型

不管模型是分割为两部分,还是多个资源,它都不会对 GEF 造成影响。术语模型 指的是整个应用程序模型。屏幕上的对象可以对应模型中的多个对象。GEF 旨在允许开发人员方便地处理这类映射。

通知策略

对视图的更新几乎应当总是来自模型的通知结果。您的模型必须提供某种通知机制,并且这种机制必须被映射到应用程序的相应更新中。只读模型或不能通知的模型可能是例外,例如文件系统或远程连接。

通知策略通常是分布式的(每个对象)或集中式的(每个域)。域通知程序了解到模型中各个对象的每项更改,并将这些更改广播到域侦听程序中。如果应用程序采用这种通知模型,则将可能为每个查看器添加一个域侦听程序。当侦听程序收到更改时,它将查找受影响的 EditPart,然后相应地再次发送更改。如果应用程序使用分布式通知,则每个 EditPart 将通常把它自己的侦听程序添加到影响它的模型对象中。


步骤 2:定义视图

下一步是确定如何使用来自 Draw2D 插件的图形来显示模型。一些图可以直接用于显示模型的对象。例如,Label 图可以用于显示 Image 和 String。有时,需要的结果可以通过组合多个图、布局管理器或边框来实现。最后,您可能要使用特定于应用程序的方法绘制您自己的图形实现。关于组合或实现图和布局的更多信息可以在 GEF SDK 附带的 Draw2D 开发者指南中找到。

在将 Draw2D 与 GEF 结合使用时,通过遵循下列原则,可以使您的项目更便于管理,并且可以更灵活地更改需求:

不要从头做起
您可以把提供的布局管理器组合在一起以呈现最多的内容。考虑使用工具栏布局(垂直方向或水平方向)和边框布局的组合来组合多个图。编写自己的布局管理器只能是最后一种手段。作为一个参考点,请查看 GEF 中提供的调色板。调色板是使用 Draw2D 中的许多标准图和布局来呈现的。
使 EditPart 与图形 “彻底” 分离
如果 EditPart 使用多个图、布局和边框的组合结构,那么请尽量对 EditPart 隐藏详细信息。让 EditPart 自己构建所有东西是可能的(但不是个好主意)。不过这样做并不会导致控制器和视图之间 “彻底” 分离。EditPart 非常熟悉图形结构,因此以类似的 EditPart 重用该结构是不可能的。此外,更改外观或结构可能会导致意外的错误。您应当转而编写自己的 Figure 子类,它将隐藏结构的详细信息。然后在 EditPart(控制器)用于更新视图的子类上定义最少数量的 API。这种被称为关注点分离 的实践将带来更大程度的重用和更少的错误。
不要从图形中引用模型或 EditPart
图形不应该具有对 EditPart 或模型的访问权。在某些情况下,EditPart 可以把自身作为侦听程序添加到图中,但是它将只能是一个侦听程序,而不是 EditPart。这种解耦实践还将带来更大程度的重用。
使用内容窗格
有时,您有包含其他图形元素的容器,但是您需要围绕容器外部进行装饰。例如,一个 UML 类通常显示为框,其顶部标有类名,可能还有一些原型,底部是为属性和方法保留的。这可以通过组合多个图来完成。第一张图是类的标题框,而另一张图被指定为内容窗格。这张图将最终将包含属性和方法的图。在稍后编写 EditPart 实现时,指明内容窗格应当用作所有子元素的父元素没有多大价值。

步骤 3:编写 EditPart

接下来,我们将用控制器或 EditPart 在模型与视图之间架起桥梁。该步骤在 GEF 中放置 “框架”。提供的类是抽象的,因此客户必须实际编写代码。结果证明,子分类方法不但十分常用,而且还可能是从模型映射到视图最灵活也是最直接的方法。

所提供的用于生成子类的基本实现有三种。将 AbstractTreeEditPart 用于树查看器中显示的 EditPart。在图形查看器中展开 AbstractGraphicalEditPartAbstractConnectionEditPart。在这里,我们将主要介绍图形 EditPart。相同的原则同样适用于树查看器。

EditPart 生命周期

在编写 EditPart 之前,了解 EditPart 的来源,以及当不再需要 EditPart 时怎样处理它们,将很有帮助。每个查看器都配备了一个工厂用以创建 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(表示图表中的条目)可能有需要图形化显示的数据。它们还可能有自己的结构,例如连接或自己的子 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 将处理把相对约束转换为绝对位置的工作,并且可用它来将图形自动调整为理想的大小(换言之,当约束的宽度和高度均为 -1 时)。

方法 refreshVisuals() 只在 EditPart 的初始化过程中调用一次并且决不再次调用。响应模型通知时,应用程序将负责根据需要再次调用 refreshVisuals() 以更新图。为了提高性能,您可能希望抽取每个模型属性的代码放到它自己的方法中(或者带有 “开关” 的单个方法)。那样,当模型发出通知时,将运行最少量的代码,只刷新发生更改的部分。

另一个有趣的区别是连接支持的代码。类似于 getModelChildren()getModelSourceConnections()getModelTargetConnections() 应当返回表示节点之间链接的模型对象。超类将在必要时创建相应的 EditPart 并将其添加到源连接 EditPart 和目标连接 EditPart 的列表。注:连接是被两端的节点引用的,但是连接的 EditPart 只需要创建一次。GEF 将通过首先在查看器中查看连接是否已经存在来确保连接只被创建一次。

建立连接

编写连接 EditPart 实现没有太大的区别。首先生成 AbstractConnectionEditPart 的子类。跟前面一样,refreshVisuals() 将实现把属性从模型映射到图形中。连接可能还有约束,但是这些约束与以前的约束略有不同。在这里,连接路由器使用了限制来限制连接。而且,连接 EditPart 的图必须为 Draw2D Connection,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());
    }

    ...
}

获得连接的方法是在现有连接 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));
    }
}

侦听模型

创建后,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();
    }

    ...
}

编辑模型

提示 2

不要忘记真正实现 NodeEditPart 接口。否则,您的方法将永远不会得到调用。

最重要的是,知道何时使用 ConnectionEditPart,而何时不使用 ConnectionEditPart。当用户可以选择某些内容并可与之交互时,将使用连接 EditPart。它可能与模型中的某个对象直接相关,并且通常可由自己删除。

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

连接始终都必须有源和目标。如果需要可以在没有源或目标的情况下存在的连接,您最好只继承 AbstractGraphicalEditPart 并使用连接图形。

到目前为止,我们已经介绍了如何创建 EditPart、如何创建 EditPart 的可视图以及当模型发生更改时 EditPart 如何进行更新。除此之外,EditPart 也是对模型进行更改的主要参与者。当命令的请求被发送给 EditPart 时就会发生这种情况。请求还用于要求 EditPart 显示诸如在拖动鼠标时产生的反馈。EditPart 可能支持、阻止给定请求,也可能忽略给定请求。所支持或阻止的请求类型决定了 EditPart 的行为。

侧重点到目前为止都是如何将模型的结构和属性映射到视图中。结果表明,这基本上是在 EditPart 类本身中所做的全部工作。其行为是由一组称为 EditPolicies 的可插入的助手类决定的。在所提供的示例中,我们忽略了方法 createEditPolicies()。实现此方法后,就几乎已经完成了 EditPart。当然,仍需要提供知道如何修改应用程序模型的编辑策略。由于编辑行为是可插入的,因此在开发各种 EditPart 实现时,可以根据将模型映射到视图和处理模型更新的任务来创建类层次结构。


步骤 4:将所有内容组合在一起

现在,您已经拥有了以图形方式显示模型所需的全部组成部分。对于最终整合,我们将使用 IEditorPart。不过,在视图、对话框或者可以放置控件的任意位置也都可以使用 GEF 的查看器。对于此步骤,您必须拥有自己的 UI 插件,它将为正被打开的资源定义编辑器和文件扩展名。可以在同一个插件中定义模型,也可以在独立插件中定义模型。您还需要一个预填充的模型,因为目前还没有编辑功能。

有若干种方法可用于提供样例模型数据。出于本示例的目的,我们将在编辑器被打开时在代码中创建模型,而忽略文件的实际内容。要做到这一点,我们假定已经存在一个测试工厂。或者,您可以创建一个示例向导,该向导将用数据预填充资源(普通向导只创建空图)。最后,您可以用文本编辑器手动编写文档的内容。

现在您有了样例模型,让我们创建将显示模型的编辑器部件。快速开始的方法就是生成子类或复制 GEF 的 GraphicalEditor。此类将创建 ScrollingGraphicalViewer 的实例,并构造画布用作编辑器的控件。它是十分方便的类,用于帮助您开始使用 GEF;正常工作的 Eclipse 编辑器需要考虑很多其他事情,例如不利的团队环境、正在删除或移动的资源等。

清单 6 显示了一个样例编辑器实现。有几个必须实现的抽象方法。鉴于本文讨论范围的限制,我们将忽略模型持久性和标记。要让图出现在图形查看器中,必须先做两件事:使用您自己的 EditPart 工厂配置查看器,以从 步骤 3 构造 EditPart;然后把图模型对象传递给查看器。


清单 6. 实现编辑器部件
                
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 初学者查看 图形示例,以及 Bo Majewski 撰写的优秀文章 “A Shape Diagram Editor”(请参阅 参考资料)。

随着 GEF 不断成熟,已经有很多构建在 GEF 基础上的健壮框架可以简化在 Eclipse 中开发图形编辑器的过程。必须提及这些框架的原因是,在很多情况下,开发人员都使用这些框架而不是直接在 GEF 本身上构建。

图形模型框架(Graphical Modeling Framework,GMF)

GMF 项目是从手动创建图形编辑器的挫败中产生而来(尤其是在使用 Eclipse Modeling Framework 的环境中)。GMF 将使您可以把语义(商业逻辑)模型高效映射到概念(图形)模型(参见图 5)。使用一些配置文件完成此映射后,GMF 将为您生成一个功能全面的图形编辑器。


图 5. GMF 开发流程
GMF 开发流程

如果用例需要将 Eclipse Modeling Framework 用于模型,则强烈建议使用 GMF 而不是直接使用 GEF。有关更多信息,请阅读 Chris Aniszczyk 的 “Learn Eclipse GMF in 15 minutes”(请参阅 参考资料)。

Zest

Zest 是一个轻量级可视化工具包(参见图 6),该工具包将在传统 GEF 编辑器顶部提供类似于 JFace 的包装。Zest 已经在 JFace 之后被模型化,并且所有 Zest 视图都与现有的 Eclipse 视图一样遵守相同的标准和约定(认为包括标签和内容提供程序)。这意味着可以在 Zest 中利用现有应用程序中使用的提供程序、操作和侦听程序。此外,Zest 拥有可重用布局,可以轻松地应用到您的可视化结果中。


图 6. 样例 Zest 可视化
样例 Zest 可视化

如果用例只需考虑可视化而不需考虑编辑,建议使用 Zest 提供的工具。如果不巧使用了其他可视化工具包,Zest 的布局设计也可以支持其他工具包的重用。


结束语

本文的目的在于提供关于 GEF 的优秀介绍,本文的前五部分讨论了 GEF。在那之后,讨论了倾向于图形化的 Eclipse 开发人员在 GEF 领域外部可用的若干个选项。最后,评估用例并查看哪种图形框架能够最好地满足需求非常重要。

<!-- CMA ID: 237383 --><!-- Site ID: 10 --><!-- XSLT stylesheet used to transform this file: dw-article-6.0-beta.xsl -->

参考资料

学习

获得产品和技术

讨论

  • 想要为 GEF 做出贡献?请查阅 GEF 开发邮件列表

  • 查阅 GMF 新闻组 以了解错综复杂的 GMF(选择此链接将启动默认的 Usenet 新闻阅读器应用程序并打开 eclipse.modeling.gmf)。

  • Eclipse Platform 新闻组 应当是讨论关于 Eclipse 的问题的第一站(选择此链接将启动默认的 Usenet 新闻阅读器应用程序并打开 eclipse.platform)。

  • 查阅 GEF 新闻组 以获得开发帮助(选择此链接将启动默认的 Usenet 新闻阅读器应用程序并打开 eclipse.tools.gef)。

  • Eclipse 新闻组 中有很多参考资料适用于对使用和扩展 Eclipse 感兴趣的人员。

  • 参与 developerWorks blog,加入 developerWorks 社区。

作者简介

Randy Hudson:软件开发人员,IBM。

Chris Aniszczyk

Chris Aniszczyk 是 IBM Lotus 的软件工程师,专门从事 OSGi 相关开发工作。他是开放源码的忠实拥护者,目前在开发 Gentoo Linux 发行版,他还是一些 Eclipse 项目(PDE、ECF、EMFT)的参与者。他十分 乐意与您讨论 关于开放源码和 Eclipse 方面的问题。

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics