使用图形编辑框架创建基于 Eclipse 的应用程序
倾向于使用图形的 Eclipse 开发人员如何开始使用 GEF 和其他选项
简介: 了解使用图形编辑框架(Graphical Editing Framework,GEF)创建基于 Eclipse 的应用程序涉及的最初步骤。此外,介绍了目前在 Eclipse 中引导创建图形编辑器过程使用的选项。
本文将介绍使用图形编辑框架(Graphical Editing Framework,GEF)的步骤。我们不是完整地完成每个步骤,而是将使用您的应用程序模型的子集,并先使该子集工作。例如,开始我们可能会忽略连接,或者只注意应用程序中图形元素类型的子集。接下来,了解其他可向应用程序添加图形编辑功能的技术。过去,独立 GEF 曾是在 Eclipse 中进行图形编辑的惟一选择,但是这种情况随着 Eclipse 的发展而发生了改变。
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 Tree
和 TreeItem
用于其视图。
GEF 对模型一无所知。任何模型类型应当都能运行,只要它满足下面描述的属性。
一切尽在模型中。模型是惟一被存储和恢复的内容。应用程序应当把所有重要数据存储到模型中。在编辑、撤消和重做的过程中,模型是惟一保持不变的。图形和 EditPart 在经过一段时间后将被回收和重建。
当用户与 EditPart
进行交互时,模型不是由 EditPart
直接处理的。相反,将创建 Command
以封装更改。Command
可用于验证用户的交互,并可用于提供撤消和重做支持。
严格来说,Command
也属于模型的概念范畴。它们本质上不是模型,但是是编辑模型的方法。命令用于执行所有用户的撤消更改。在理想的情况下,命令应当只知道模型。它们应当避免引用 EditPart
或图形。类似地,只要可能,命令应当避免调用用户界面(例如弹出式对话框)。
简单的 GEF 应用程序是用于绘制图形的编辑器。(在这里,图形 仅指图片,而不是类图)。图形可以被模块化为一些形状(shape)。形状可能拥有位置、颜色等属性,并且可能是多个形状构成的一组结构。这里没有什么可惊讶的,并且以前的要求也很易于维护。
图 2. 简单模型

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

不管模型是分割为两部分,还是多个资源,它都不会对 GEF 造成影响。术语模型 指的是整个应用程序模型。屏幕上的对象可以对应模型中的多个对象。GEF 旨在允许开发人员方便地处理这类映射。
对视图的更新几乎应当总是来自模型的通知结果。您的模型必须提供某种通知机制,并且这种机制必须被映射到应用程序的相应更新中。只读模型或不能通知的模型可能是例外,例如文件系统或远程连接。
通知策略通常是分布式的(每个对象)或集中式的(每个域)。域通知程序了解到模型中各个对象的每项更改,并将这些更改广播到域侦听程序中。如果应用程序采用这种通知模型,则将可能为每个查看器添加一个域侦听程序。当侦听程序收到更改时,它将查找受影响的 EditPart
,然后相应地再次发送更改。如果应用程序使用分布式通知,则每个 EditPart
将通常把它自己的侦听程序添加到影响它的模型对象中。
下一步是确定如何使用来自 Draw2D 插件的图形来显示模型。一些图可以直接用于显示模型的对象。例如,Label 图可以用于显示 Image 和 String。有时,需要的结果可以通过组合多个图、布局管理器或边框来实现。最后,您可能要使用特定于应用程序的方法绘制您自己的图形实现。关于组合或实现图和布局的更多信息可以在 GEF SDK 附带的 Draw2D 开发者指南中找到。
在将 Draw2D 与 GEF 结合使用时,通过遵循下列原则,可以使您的项目更便于管理,并且可以更灵活地更改需求:
接下来,我们将用控制器或 EditPart 在模型与视图之间架起桥梁。该步骤在 GEF 中放置 “框架”。提供的类是抽象的,因此客户必须实际编写代码。结果证明,子分类方法不但十分常用,而且还可能是从模型映射到视图最灵活也是最直接的方法。
所提供的用于生成子类的基本实现有三种。将 AbstractTreeEditPart
用于树查看器中显示的 EditPart。在图形查看器中展开 AbstractGraphicalEditPart
和 AbstractConnectionEditPart
。在这里,我们将主要介绍图形 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

内容的图并不太令人感兴趣,并且通常只是包含图的子元素的空面板。它的图形应该为不透明类型(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”,表明应当为该图提供理想的大小。
方法 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(); } ... } |
到目前为止,我们已经介绍了如何创建 EditPart、如何创建 EditPart 的可视图以及当模型发生更改时 EditPart 如何进行更新。除此之外,EditPart 也是对模型进行更改的主要参与者。当命令的请求被发送给 EditPart 时就会发生这种情况。请求还用于要求 EditPart 显示诸如在拖动鼠标时产生的反馈。EditPart 可能支持、阻止给定请求,也可能忽略给定请求。所支持或阻止的请求类型决定了 EditPart 的行为。
侧重点到目前为止都是如何将模型的结构和属性映射到视图中。结果表明,这基本上是在 EditPart 类本身中所做的全部工作。其行为是由一组称为 EditPolicies 的可插入的助手类决定的。在所提供的示例中,我们忽略了方法 createEditPolicies()
。实现此方法后,就几乎已经完成了 EditPart。当然,仍需要提供知道如何修改应用程序模型的编辑策略。由于编辑行为是可插入的,因此在开发各种 EditPart 实现时,可以根据将模型映射到视图和处理模型更新的任务来创建类层次结构。
现在,您已经拥有了以图形方式显示模型所需的全部组成部分。对于最终整合,我们将使用 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 开发流程

如果用例需要将 Eclipse Modeling Framework 用于模型,则强烈建议使用 GMF 而不是直接使用 GEF。有关更多信息,请阅读 Chris Aniszczyk 的 “Learn Eclipse GMF in 15 minutes”(请参阅 参考资料)。
Zest 是一个轻量级可视化工具包(参见图 6),该工具包将在传统 GEF 编辑器顶部提供类似于 JFace 的包装。Zest 已经在 JFace 之后被模型化,并且所有 Zest 视图都与现有的 Eclipse 视图一样遵守相同的标准和约定(认为包括标签和内容提供程序)。这意味着可以在 Zest 中利用现有应用程序中使用的提供程序、操作和侦听程序。此外,Zest 拥有可重用布局,可以轻松地应用到您的可视化结果中。
图 6. 样例 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 -->学习
- 您可以参阅本文在 developerWorks 全球站点上的 英文原文 。
- 访问 Eclipse 图形编辑框架(Graphical Editing Framework,GEF)以了解关于图形编辑框架的更多信息。
- 刚刚接触 GEF 并且需要一个简单而具体的示例?请在 Eclipse.org 查阅 Bo Majewski 撰写的图形示例文章:“A Shape Diagram Editor”。
- 在 Eclipse.org 查阅 GEF 模式编辑器文章 “Building a Database Schema Diagram Editor with GEF”。
- 阅读 GEF 程序员指南 以获得关于 GEF 的(大概)定义性文档。
- 查阅 Eclipse Modeling Framework (EMF) 以获得会对 EMF 初学者有帮助的教程和文档。
- EMF 团队有一篇标题为 “Generating an EMF Model” 的优秀介绍性教程。
- 如果需要关于 EMF 的定义性资源,则 Eclipse Modeling Framework: A Developer's Guide 是本不错的参考书。
- 要获得 GMF 的快速概览,请阅读 “15 分钟学会 Eclipse GMF”。
- Frederic Plante 撰写了一篇标题为 “Introducing the GMF Runtime” 的文章,详细说明了 GMF 运行时的高级功能。
-
Graphical Modeling Framework 维基 提供了关于 GMF 高级功能的教程和大量信息。
- 通过 Richard Gronback 和 Ed Merks 的这个 webinar 了解使用各种 Eclipse 模型框架的信息。
- 在 Eclipse.org 了解 Zest: The Eclipse Visualization Toolkit。
- 要获得关于 Eclipse 平台的介绍性文章,请参阅 “Eclipse 平台入门”。
- 查阅 “Eclipse 推荐读物列表”。
- 查阅 IBM developerWorks 的 Eclipse 项目资源 扩展 PHP 技巧。
- 收听针对软件开发人员的有趣访谈和讨论,一定要访问 developerWorks podcast。
- 随时关注 developerWorks 的 技术事件和网络广播。
- 查阅最近将在全球举办的面向 IBM 开放源码开发人员的研讨会、交易展览、网络广播和其他 活动。
- 访问 developerWorks 开放源码专区,获得丰富的 how-to 信息、工具和项目更新,帮助您用开放源码技术进行开发,并与 IBM 产品结合使用。
获得产品和技术
- 下载 Eclipse 并立即开始使用 Eclipse。
- 在 IBM alphaWorks 中查阅最新的 Eclipse 技术下载。
- 使用 IBM 试用软件 构建您的下一个开发项目,这些软件可以通过下载或从 DVD 中获得。
讨论
- 想要为 GEF 做出贡献?请查阅 GEF 开发邮件列表。
- 查阅 GMF 新闻组 以了解错综复杂的 GMF(选择此链接将启动默认的 Usenet 新闻阅读器应用程序并打开 eclipse.modeling.gmf)。
-
Eclipse Platform 新闻组 应当是讨论关于 Eclipse 的问题的第一站(选择此链接将启动默认的 Usenet 新闻阅读器应用程序并打开 eclipse.platform)。
- 查阅 GEF 新闻组 以获得开发帮助(选择此链接将启动默认的 Usenet 新闻阅读器应用程序并打开 eclipse.tools.gef)。
-
Eclipse 新闻组 中有很多参考资料适用于对使用和扩展 Eclipse 感兴趣的人员。
- 参与 developerWorks blog,加入 developerWorks 社区。

Chris Aniszczyk 是 IBM Lotus 的软件工程师,专门从事 OSGi 相关开发工作。他是开放源码的忠实拥护者,目前在开发 Gentoo Linux 发行版,他还是一些 Eclipse 项目(PDE、ECF、EMFT)的参与者。他十分 乐意与您讨论 关于开放源码和 Eclipse 方面的问题。
相关推荐
BIRT(Business Intelligence and Reporting Tools)是一个基于Eclipse的开源报表系统,主要应用于Java和J2EE的Web应用程序。该系统由两大部分组成:一是Eclipse集成的报表设计工具,二是可嵌入到应用程序中的运行时...
J++,全称Visual J++,是微软在Java 1.1时代推出的一款集成开发环境(IDE),用于开发基于Windows平台的Java应用程序。它是对Microsoft Visual Studio系列产品的扩展,提供了与Visual Basic相似的可视化设计界面,...
物联网设备开发_蓝牙低能耗BLE技术_小米手环1非心率版数据读取与控制_实现Android平台下小米手环1代非心率版设备的蓝牙连接_步数数据获取_电量监测_震动控制功能_适用于An
内容概要:本文详细探讨了基于定子磁链定向矢量控制的双馈感应发电机(DFIG)空载并网模型。首先介绍了传统的PI控制方法,指出其在动态响应方面的局限性。接着,提出了通过引入模糊控制来改进PI控制的方法,展示了模糊控制在提高动态响应速度和减少误差方面的显著优势。文中提供了详细的代码实现和实验结果对比,证明了改进模型的有效性和优越性。 适合人群:从事电力电子、风电控制系统设计的研究人员和技术人员,尤其是对双馈感应发电机并网控制感兴趣的读者。 使用场景及目标:适用于希望深入了解DFIG并网控制策略的技术人员,旨在帮助他们掌握如何通过模糊控制优化PI控制器,以提高系统的动态响应速度和稳定性,减少并网瞬间的电流冲击。 其他说明:文章不仅提供了理论分析,还包括具体的代码实现和实验数据,便于读者理解和复现。同时,强调了模糊控制并非万能解决方案,需要结合实际情况进行调整和优化。
MuGuiLin_VoiceDictation_17128_1745869163155
termux,在安卓平台的模拟终端
内容概要:本文详细介绍了基于混合遗传算法-蚁群算法优化随机森林回归预测(GA-ACO-RFR)的MATLAB实现方法及其在电力领域的应用。首先,文章讲解了如何读取和预处理电厂运行数据,将其转化为可用于建模的数值矩阵。接着,深入探讨了GA-ACO-RFR的工作原理,包括遗传算法的全局搜索能力以及蚁群算法的局部寻优特性,并展示了具体的优化过程和关键代码。随后,文章演示了如何利用优化后的参数构建最终的随机森林回归模型,并进行了预测和评估,证明了该方法能够显著提高电厂运行数据的预测精度。此外,文中还提供了多个实用技巧,如数据归一化、种群初始化、适应度函数设计等。 适合人群:对电力数据分析感兴趣的工程师和技术人员,尤其是那些希望通过MATLAB实现复杂算法优化的人士。 使用场景及目标:适用于需要精确预测电厂运行参数(如主汽温度、发电负荷等)的场合,旨在帮助用户掌握GA-ACO-RFR的具体实现步骤,从而应用于实际项目中,达到优化电厂管理和提高能源效率的目的。 其他说明:文章不仅提供了详细的理论解释,还包括了大量的代码实例和配图,使得读者更容易理解和实践。同时,作者还分享了一些个人经验,如参数设置建议和性能优化技巧,进一步增强了文章的实用性。
内容概要:本文详细介绍了利用滑模观测器(SMO)实现永磁同步电机(PMSM)无位置传感器控制的方法及其仿真模型构建。首先解释了滑模观测器的工作原理,即通过构造滑动模态面使系统状态沿预设轨迹运动,从而估算电机的位置和转速。文中展示了具体的MATLAB/Simulink代码实现,包括滑模观测器的核心算法、锁相环(PLL)用于位置提取以及低通滤波器的应用。此外,讨论了调试过程中遇到的问题及解决方案,如滑模增益的选择、电流观测误差的处理、低速运行时的稳定性提升等。最后,通过仿真结果验证了该方案的有效性和鲁棒性。 适合人群:从事电机控制系统研究与开发的技术人员,尤其是对无位置传感器控制技术和滑模观测器感兴趣的工程师。 使用场景及目标:适用于希望减少硬件成本和复杂度,提高系统可靠性的情况。主要目标是在不使用物理位置传感器的情况下,实现对永磁同步电机的精确控制,确保系统的稳定性和响应速度。 其他说明:文中提供了丰富的代码片段和调试技巧,有助于读者快速理解和应用滑模观测器技术。同时强调了仿真与实际应用之间的差异,提醒开发者在实际部署时需要注意的问题。
知识领域_社区论坛系统_微信小程序_Java后端开发_网络安全_性能优化_技术关键词_uni-app_Vue2_SpringBoot_MybatisPlus_Redis_Mysql
# 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;
DAB转换器 双有源桥(DAB)转换器是一种高频隔离DC-DC转换器,广泛应用于电动汽车充电器、可再生能源系统。 1输入侧 使用直流电压源 使用IGBT或MOSFET连接到全桥逆变器(通用桥) 使用移相PWM发生器进行控制 2.变压器 使用理想变压器或物理变压器模型 确保隔离并设置匝数比(例如1:1,或用于升压/降压) 3.输出侧 使用另一个全桥逆变器(充当整流器) 连接直流滤波电容器和负载(或电池) 4.控制策略 实施移相控制器: 相对于输入移位输出桥门信号
内容概要:本文详细介绍了车载充电机的完整设计方案,重点探讨了LLC谐振变换器和PFC(功率因数校正)的技术细节。文中不仅提供了LLC和PFC的C语言源码示例,还深入讲解了原理图、PCB布局及变压器设计等方面的内容。LLC部分强调了谐振频率的计算及其对变换器稳定性的影响,而PFC部分则关注于功率因数的提升方法。此外,文章还分享了许多实用的设计经验和调试技巧,如PCB布局的注意事项、变压器参数的选择等。 适合人群:从事车载充电技术研发的工程师和技术爱好者,尤其是希望深入了解LLC和PFC技术原理的人群。 使用场景及目标:帮助工程师优化车载充电机的设计,提高产品的性能和可靠性,同时为初学者提供全面的学习资料,加速技术掌握。 其他说明:文中提供的方案不仅适用于车载充电机,还可以应用于其他类似设备的研发,如吸尘器电源等。通过实际案例和详细的调试指南,使读者能够更好地理解和应用相关技术。
# 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;
内容概要:本文详细介绍了基于西门子PLC(如S7-1200和S7-200)和组态王6.55构建的锅炉控制系统。主要内容涵盖梯形图程序设计、硬件接线图、IO分配以及组态画面的设计。文章首先解释了锅炉控制的基本原理,包括手动模式和自动PID调节的梯形图逻辑,接着讨论了温度、压力等重要参数的采集与处理方法。此外,还探讨了组态王画面设计技巧,如动态属性绑定、动画效果实现等。最后分享了一些调试经验和优化建议,强调了安全冗余设计的重要性。 适合人群:从事工业自动化领域的工程师和技术人员,特别是熟悉PLC编程和HMI开发的专业人士。 使用场景及目标:适用于新建或改造锅炉控制系统项目,旨在帮助技术人员掌握完整的系统设计方案,确保系统稳定可靠运行,减少故障发生率,降低维护成本。 其他说明:文中提供了大量实际案例和经验总结,对于理解和应用工业自动化技术具有很高的参考价值。
scratch少儿编程逻辑思维游戏源码-海底冒险.zip
# 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;
# 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;
内容概要:本文详细介绍了基于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参数整定、硬件联调等问题。同时,提供的代码示例可以直接应用于类似场景,减少了重复开发的工作量。
# 压缩文件中包含: 中文文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;
# 压缩文件中包含: 中文-英文对照文档 jar包下载地址 Maven依赖 Gradle依赖 源代码下载地址 # 本文件关键字: jar中文-英文对照文档.zip,java,jar包,Maven,第三方jar包,组件,开源组件,第三方组件,Gradle,中文API文档,手册,开发手册,使用手册,参考手册 # 使用方法: 解压最外层zip,再解压其中的zip包,双击 【index.html】 文件,即可用浏览器打开、进行查看。 # 特殊说明: ·本文档为人性化翻译,精心制作,请放心使用。 ·只翻译了该翻译的内容,如:注释、说明、描述、用法讲解 等; ·不该翻译的内容保持原样,如:类名、方法名、包名、类型、关键字、代码 等。 # 温馨提示: (1)为了防止解压后路径太长导致浏览器无法打开,推荐在解压时选择“解压到当前文件夹”(放心,自带文件夹,文件不会散落一地); (2)有时,一套Java组件会有多个jar,所以在下载前,请仔细阅读本篇描述,以确保这就是你需要的文件;