`

(转载)使用图形编辑框架创建基于 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 方面的问题。

分享到:
评论

相关推荐

    birt经验之谈转载

    BIRT(Business Intelligence and Reporting Tools)是一个基于Eclipse的开源报表系统,主要应用于Java和J2EE的Web应用程序。该系统由两大部分组成:一是Eclipse集成的报表设计工具,二是可嵌入到应用程序中的运行时...

    j++学习资料

    J++,全称Visual J++,是微软在Java 1.1时代推出的一款集成开发环境(IDE),用于开发基于Windows平台的Java应用程序。它是对Microsoft Visual Studio系列产品的扩展,提供了与Visual Basic相似的可视化设计界面,...

    物联网设备开发_蓝牙低能耗BLE技术_小米手环1非心率版数据读取与控制_实现Android平台下小米手环1代非心率版设备的蓝牙连接_步数数据获取_电量监测_震动控制功能_适用于An.zip

    物联网设备开发_蓝牙低能耗BLE技术_小米手环1非心率版数据读取与控制_实现Android平台下小米手环1代非心率版设备的蓝牙连接_步数数据获取_电量监测_震动控制功能_适用于An

    定子磁链定向矢量控制与模糊控制相结合的DFIG空载并网模型及改进效果分析

    内容概要:本文详细探讨了基于定子磁链定向矢量控制的双馈感应发电机(DFIG)空载并网模型。首先介绍了传统的PI控制方法,指出其在动态响应方面的局限性。接着,提出了通过引入模糊控制来改进PI控制的方法,展示了模糊控制在提高动态响应速度和减少误差方面的显著优势。文中提供了详细的代码实现和实验结果对比,证明了改进模型的有效性和优越性。 适合人群:从事电力电子、风电控制系统设计的研究人员和技术人员,尤其是对双馈感应发电机并网控制感兴趣的读者。 使用场景及目标:适用于希望深入了解DFIG并网控制策略的技术人员,旨在帮助他们掌握如何通过模糊控制优化PI控制器,以提高系统的动态响应速度和稳定性,减少并网瞬间的电流冲击。 其他说明:文章不仅提供了理论分析,还包括具体的代码实现和实验数据,便于读者理解和复现。同时,强调了模糊控制并非万能解决方案,需要结合实际情况进行调整和优化。

    MuGuiLin_VoiceDictation_17128_1745869163155.zip

    MuGuiLin_VoiceDictation_17128_1745869163155

    termux 安卓平台的应用

    termux,在安卓平台的模拟终端

    基于GA-ACO算法优化的随机森林回归预测(GA-ACO-RFR)在MATLAB中实现,附带清晰代码注释,适合初学者,以电厂运行数据为例

    内容概要:本文详细介绍了基于混合遗传算法-蚁群算法优化随机森林回归预测(GA-ACO-RFR)的MATLAB实现方法及其在电力领域的应用。首先,文章讲解了如何读取和预处理电厂运行数据,将其转化为可用于建模的数值矩阵。接着,深入探讨了GA-ACO-RFR的工作原理,包括遗传算法的全局搜索能力以及蚁群算法的局部寻优特性,并展示了具体的优化过程和关键代码。随后,文章演示了如何利用优化后的参数构建最终的随机森林回归模型,并进行了预测和评估,证明了该方法能够显著提高电厂运行数据的预测精度。此外,文中还提供了多个实用技巧,如数据归一化、种群初始化、适应度函数设计等。 适合人群:对电力数据分析感兴趣的工程师和技术人员,尤其是那些希望通过MATLAB实现复杂算法优化的人士。 使用场景及目标:适用于需要精确预测电厂运行参数(如主汽温度、发电负荷等)的场合,旨在帮助用户掌握GA-ACO-RFR的具体实现步骤,从而应用于实际项目中,达到优化电厂管理和提高能源效率的目的。 其他说明:文章不仅提供了详细的理论解释,还包括了大量的代码实例和配图,使得读者更容易理解和实践。同时,作者还分享了一些个人经验,如参数设置建议和性能优化技巧,进一步增强了文章的实用性。

    基于滑模观测技术的永磁同步电机无位置传感器控制仿真模型研究

    内容概要:本文详细介绍了利用滑模观测器(SMO)实现永磁同步电机(PMSM)无位置传感器控制的方法及其仿真模型构建。首先解释了滑模观测器的工作原理,即通过构造滑动模态面使系统状态沿预设轨迹运动,从而估算电机的位置和转速。文中展示了具体的MATLAB/Simulink代码实现,包括滑模观测器的核心算法、锁相环(PLL)用于位置提取以及低通滤波器的应用。此外,讨论了调试过程中遇到的问题及解决方案,如滑模增益的选择、电流观测误差的处理、低速运行时的稳定性提升等。最后,通过仿真结果验证了该方案的有效性和鲁棒性。 适合人群:从事电机控制系统研究与开发的技术人员,尤其是对无位置传感器控制技术和滑模观测器感兴趣的工程师。 使用场景及目标:适用于希望减少硬件成本和复杂度,提高系统可靠性的情况。主要目标是在不使用物理位置传感器的情况下,实现对永磁同步电机的精确控制,确保系统的稳定性和响应速度。 其他说明:文中提供了丰富的代码片段和调试技巧,有助于读者快速理解和应用滑模观测器技术。同时强调了仿真与实际应用之间的差异,提醒开发者在实际部署时需要注意的问题。

    知识领域_社区论坛系统_微信小程序_Java后端开发_网络安全_性能优化_技术关键词_uni-app_Vue2_SpringBoot_MybatisPlus_Redis_Mysql.zip

    知识领域_社区论坛系统_微信小程序_Java后端开发_网络安全_性能优化_技术关键词_uni-app_Vue2_SpringBoot_MybatisPlus_Redis_Mysql

    thymeleaf-1.1.1.jar中文-英文对照文档.zip

    # 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    双有源桥(DAB)转换器 高频隔离DC-DC转换器

    DAB转换器 双有源桥(DAB)转换器是一种高频隔离DC-DC转换器,广泛应用于电动汽车充电器、可再生能源系统。 1输入侧 使用直流电压源 使用IGBT或MOSFET连接到全桥逆变器(通用桥) 使用移相PWM发生器进行控制 2.变压器 使用理想变压器或物理变压器模型 确保隔离并设置匝数比(例如1:1,或用于升压/降压) 3.输出侧 使用另一个全桥逆变器(充当整流器) 连接直流滤波电容器和负载(或电池) 4.控制策略 实施移相控制器: 相对于输入移位输出桥门信号

    车载充电器技术迭代全方案:LLC与PFC源码、原理图、PCB设计与变压器专业指导

    内容概要:本文详细介绍了车载充电机的完整设计方案,重点探讨了LLC谐振变换器和PFC(功率因数校正)的技术细节。文中不仅提供了LLC和PFC的C语言源码示例,还深入讲解了原理图、PCB布局及变压器设计等方面的内容。LLC部分强调了谐振频率的计算及其对变换器稳定性的影响,而PFC部分则关注于功率因数的提升方法。此外,文章还分享了许多实用的设计经验和调试技巧,如PCB布局的注意事项、变压器参数的选择等。 适合人群:从事车载充电技术研发的工程师和技术爱好者,尤其是希望深入了解LLC和PFC技术原理的人群。 使用场景及目标:帮助工程师优化车载充电机的设计,提高产品的性能和可靠性,同时为初学者提供全面的学习资料,加速技术掌握。 其他说明:文中提供的方案不仅适用于车载充电机,还可以应用于其他类似设备的研发,如吸尘器电源等。通过实际案例和详细的调试指南,使读者能够更好地理解和应用相关技术。

    thymeleaf-2.0.9.jar中文-英文对照文档.zip

    # 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    基于西门子PLC与组态王的锅炉智能控制系统:梯形图程序、接线图与IO分配全解析

    内容概要:本文详细介绍了基于西门子PLC(如S7-1200和S7-200)和组态王6.55构建的锅炉控制系统。主要内容涵盖梯形图程序设计、硬件接线图、IO分配以及组态画面的设计。文章首先解释了锅炉控制的基本原理,包括手动模式和自动PID调节的梯形图逻辑,接着讨论了温度、压力等重要参数的采集与处理方法。此外,还探讨了组态王画面设计技巧,如动态属性绑定、动画效果实现等。最后分享了一些调试经验和优化建议,强调了安全冗余设计的重要性。 适合人群:从事工业自动化领域的工程师和技术人员,特别是熟悉PLC编程和HMI开发的专业人士。 使用场景及目标:适用于新建或改造锅炉控制系统项目,旨在帮助技术人员掌握完整的系统设计方案,确保系统稳定可靠运行,减少故障发生率,降低维护成本。 其他说明:文中提供了大量实际案例和经验总结,对于理解和应用工业自动化技术具有很高的参考价值。

    scratch少儿编程逻辑思维游戏源码-海底冒险.zip

    scratch少儿编程逻辑思维游戏源码-海底冒险.zip

    aws-java-sdk-s3-1.12.258.jar中文-英文对照文档.zip

    # 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    thymeleaf-2.0.15.jar中文-英文对照文档.zip

    # 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    S7-1500与TP1500 PID温控与压力调节的完整应用案例:包含PLC与触摸屏通讯程序及STL语言编程详解

    内容概要:本文详细介绍了基于S7-1500 PLC和TP1500触摸屏的PID温度压力调节系统的应用案例。首先解释了PID控制的基础概念及其在S7-1500中的具体实现方法,包括使用FB41功能块进行温度调节的具体参数设置。接着探讨了S7-1500 PLC间的通讯机制,展示了如何利用STL语言编写通讯程序段,确保不同PLC之间的高效数据交换。此外,还讨论了TP1500触摸屏与PLC的交互方式,如变量关联和监控画面的设计,使得操作员能够便捷地监控和调整系统参数。文中提供了丰富的代码实例和技术细节,有助于深入理解S7-1500的强大功能及其在工业自动化领域的应用。 适合人群:从事工业自动化控制的技术人员,尤其是熟悉西门子PLC编程并希望深入了解S7-1500系列产品的工程师。 使用场景及目标:适用于需要构建稳定可靠的温度压力调节系统的工业环境,如钢铁厂、化工厂等。通过学习本文,读者可以掌握PID控制的基本原理、PLC编程技巧以及触摸屏与PLC的交互设计,从而提高项目的实施效率和质量。 其他说明:文中提到的一些关键技术和编程技巧对于解决实际工程中的难题非常有价值,例如PID参数整定、硬件联调等问题。同时,提供的代码示例可以直接应用于类似场景,减少了重复开发的工作量。

    javassist-3.18.2-GA.jar中文文档.zip

    # 压缩文件中包含: 中文文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

    javassist-3.23.2-GA.jar中文-英文对照文档.zip

    # 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;

Global site tag (gtag.js) - Google Analytics