用Draw2D绘制UML图(译)

本文介绍如何利用Eclipse的Draw2D库绘制UML类图,包括创建类图的基本元素、连接线及其装饰,展示了如何通过定制化的图形和布局管理器实现特定的视觉效果。
 
Copyright © 2003 International Business Machines Corp.

Eclipse Corner Article

Display a UML Diagram using Draw2D

用Draw2D绘制UML图

Summary 摘要
The Graphical Editing Framework (GEF) ships with a painting and layout plug-in called Draw2D. Draw2D provides figures and layout managers which form the graphical layer of a GEF application. This article focuses only on the use of Draw2D to render a simple UML class diagram. While Draw2D can be used for standalone purposes, it is not an editing framework. Most applications will use the GEF plug-in as the editing layer.

图形编辑框架(GEF)运作于Draw2D之上。Draw2D是一个提供绘画和布局管理的插件,为GEF应用程序提供图形以及布局管理器来构建程序的图形表示层。本文仅着眼于如何使用Draw2D来绘制UML图。Draw2D可以独立使用,然而其并不是一个编辑框架。大多的应用程序会使用GEF插件实现编辑功能。

By Daniel Lee, IBM
August 25, 2003

Interpretted by Wayne
February 22, 2006



Introduction

介绍

Draw2d provides lightweight rendering and layout capabilities on an SWT Canvas. Figures, Layout Managers, and Borders can be combined and nested to create more complex figures to suit just about any application. Choosing the right combination of figures and layouts to create the desired effect can be a delicate task. This article will walk you through creating a complex figure.

Draw2D提供了在SWT画布上绘画以及布局的轻量级实现。图形(Figure)、布局管理器(Layout Manager),以及边框(Border)可以被任意组合和内嵌来构建复杂的图形来适应任何的应用程序。选择正确的图形组合来创建想要的图形是一件很精细微妙的工作,本文将指导你如何创建一个复杂的图形。

Due to the scope of this article, the example code presented uses Draw2d in isolation, but most applications will use GEF and Draw2d together.

由于本文的范围所限,本文的示例代码将独立使用Draw2D,但大多数的应用程序会将GEF和Draw2D结合使用。

Creating the Draw2d Figure

创建Draw2D图形

An Example 示例

This article will be based upon the creation of the following Draw2d Figure, a simplified UML class diagram:

下图是一个简单的UML类图,本文建立在创建这个图形的基础之上。

Designing the Figure 设计图形

The first step in the creation of a figure is to decide on the components that will comprise the figure, and how they will be arranged.

创建图形的第一步是确定使用什么组件来合成图形,以及它们是如何排列的。

The example figure is composed of three children figures. The composition itself is named UMLClassFigure. Its first child, a Label figure, will display the class name (”Table” in this example). The next two children are containers for the class’ attributes and methods. We will create a figure called CompartmentFigure for this purpose. Both the class and compartment figures will use a ToolbarLayout to place their children. Here is a conceptual diagram of the overall structure:

例图由三个子图形组成。图形本身为UMLClassFigure,它的第一个子图形是Label,用来显示类名(本例为“Table”),另外两个子图形是用来放置属性及方法的容器。我们将创建一个叫做CompartmentFigure的图形来达到容器的目的。UMLClassFigure和CompartmentFigure都使用ToolbarLayout来放置子图形,下图是它在概念上的上层结构图:

Creating the CompartmentFigure Class

创建CompartmentFigure类

CompartmentFigure is used to hold both methods and attributes. This class extends org.eclipse.draw2d.Figure, and uses a ToolbarLayout to place its children. In addition, CompartmentFigure uses a custom border. This border simply paints a line 1 pixel in thickness across its top, to serve as the separator between the CompartmentFigures. The code for CompartmentFigure is as follows:

CompartmentFigure用来放置方法和属性,这个类继承org.eclipse.draw2d.Figure类,并且使用ToolbarLayout来管理子图形的布局,同时,CompartmentFigure使用了一个自定义的边框。这个边框只是简单的在它的上端画一条1个象素粗细的线,作为两个CompartmentFigure的分隔。CompartmentFigure的代码如下:

public class CompartmentFigure extends Figure {

  public CompartmentFigure() {    ToolbarLayout layout = new ToolbarLayout();    layout.setMinorAlignment(ToolbarLayout.ALIGN_TOPLEFT);    layout.setStretchMinorAxis(false);    layout.setSpacing(2);    setLayoutManager(layout);    setBorder(new CompartmentFigureBorder());  }

  public class CompartmentFigureBorder extends AbstractBorder {    public Insets getInsets(IFigure figure) {      return new Insets(1,0,0,0);    }    public void paint(IFigure figure, Graphics graphics, Insets insets) {      graphics.drawLine(getPaintRectangle(figure, insets).getTopLeft(),                        tempRect.getTopRight());    }  }}

Creating the UMLClassFigure Class

创建UMLClassFigure类

The UMLClassFigure class is in many ways similar to the CompartmentFigure class. It contains three children — two CompartmentFigures for attributes and methods and a Draw2d Label to display the class name. It also uses a vertically oriented ToolbarLayout to place its children. UMLClassFigure uses Draw2d’s LineBorder to draw a box around its edges. The code for the UMLClassFigure class is as follows:

UMLClassFigure类在很多地方都和CompartmentFigure类很相似,它包含三个子图形——用来放置方法和属性的两个CompartmentFigure和一个用来显示类名的Draw2D标签(Label)。它也使用了垂直导向的ToolbarLayout来管理子图形的布局。UMLClassFirgure使用Draw2D的LineBorder在自己的边缘绘制矩形边框。

public class UMLClassFigure extends Figure {  public static Color classColor = new Color(null,255,255,206);  private CompartmentFigure attributeFigure = new CompartmentFigure();  private CompartmentFigure methodFigure = new CompartmentFigure();  public UMLClassFigure(Label name) {    ToolbarLayout layout = new ToolbarLayout();    setLayoutManager(layout);     setBorder(new LineBorder(ColorConstants.black,1));    setBackgroundColor(classColor);    setOpaque(true);

    add(name);     add(attributeFigure);    add(methodFigure);  }  public CompartmentFigure getAttributesCompartment() {    return attributeFigure;  }  public CompartmentFigure getMethodsCompartment() {    return methodFigure;  }}

Adding a Connection

增加连接

Draw2d offers a special type of figure, called a connection, for connecting two figures. To create a connection in Draw2d, it is first necessary to establish the two endpoints of the connection. These endpoints are called the source and the target anchors. Endpoints are created using objects that implement the ConnectionAnchor interface. Once these anchors are created, they are set as endpoints via calls to the connection’s setSourceAnchor(ConnectionAnchor) and setTargetAnchor(ConnectionAnchor) methods. This is demonstrated below using a ChopboxAnchor. This type of anchor places the connection endpoint on the edge of the figure and causes it to point towards the figure’s center.

Draw2D提供了一种成为连接(Connection)特殊的图形,用来连接两个图形。要在Draw2D中创建连接,首先要创建连接的两个端点(endpoint)。这辆个端点成为源支撑点(source anchor)和目标支撑点(target anchor)。端点由实现了ConnectionAnchor接口的类来创建。在支撑点创建好后,便可通过调用setSourceAnchor(ConnectionAnchor)方法和setTargetAnchor(ConnectionAnchor)方法来将其设定为端点。本例使用了称为ChopboxAnchor的支撑点,这种支撑点将端点放置在图形的边缘,并且将方向指向图形的中心。

The following code demonstrates the addition of a connection:

以下代码增加了一个连接:

PolylineConnection c = new PolylineConnection();ChopboxAnchor sourceAnchor = new ChopboxAnchor(classFigure);ChopboxAnchor targetAnchor = new ChopboxAnchor(classFigure2);c.setSourceAnchor(sourceAnchor);c.setTargetAnchor(targetAnchor);


Two UMLClassFigures connected by a PolyLineConnection

由PolyLineConnection连接的两个UMLClassFirgure

Adding a Decoration to the Connection

连接的装饰

Draw2d also provides means for endpoint decorations, such as arrow-tips. Staying with the UML theme, we will create a decoration that represents a composed relationship, which is shown in UML as a filled diamond. This is done using a PolygonDecoration. The default shape of a PolygonDecoration is a filled arrowhead, but any shape can be used by creating a template for the decoration using a PointList, and calling the PolygonDecoration’s setTemplate(PointList) method.

Draw2d同时也为端点提供了箭头等形状的可以具有一定意义的装饰。和UML一样,我们将创建一个实心的菱形装饰来表示组合关系。这将由PolygonDecoration来实现。PolygonDecoration的缺省形状是实心箭头,然而可以通过创建新模板来实现任何形状。模板由PointList定义,通过调用setTemplate(PointList)来指定。

The following code demonstrates the addition of a PolygonDecoration to a Connection:

以下代码演示了如何将PolygonDecoration加到连接上去:

PolygonDecoration decoration = new PolygonDecoration();PointList decorationPointList = new PointList();decorationPointList.addPoint(0,0);decorationPointList.addPoint(-2,2);decorationPointList.addPoint(-4,0);decorationPointList.addPoint(-2,-2);decoration.setTemplate(decorationPointList);c.setSourceDecoration(decoration);


Connection with a PolygonDecoration

具有PolygonDecoration的连接

Adding Labels to the Connection Using Locators

使用Locator给连接加上标签

In addition to decorations, it is possible to add other Draw2d figures to the connection itself. This is done by calling the connection’s add(IFigure figure, Object constraint) method where ‘figure’ is the figure that you wish to add, and ‘constraint’ is an object that implements the Locator interface. The Locator places the figure on the connection. We will use this technique to add labels to our class diagram. The ConnectionEndpointLocator will be used for these labels. This locator places its figure relative to the connection’s source or target endpoint. It allows the user to define the distance that the figure will appear relative to the end point via its setUDistance(int) and setVDistance(int) methods. (uDistance is the distance from the connection’s owner to the figure. vDistance is the distance from the figure to the connection itself).

除了装饰之外,我们还可以给连接增加其他的Draw2d图形。这可以通过调用连接的add(IFigure figure, Object constratint)方法实现,其中figure为要增加的图形,constraint是一个实现了Locator接口的类,由Locator将图形放置在连接上。我们将使用这种技术来为我们的类图加上标签。ConnectionEndpointLocator可以将图形放置在连接的源端点或目标端点上,因而我们选用它来放置标签。我们还可以通过调用setUDistance(int)和setVDistance(int)方法来指定图形与端点的举例(其中uDistance是连接的图形到将要加上去的图形的距离,而vDistance则是将要加上的图形到连接本身的举例)。

The following code demonstrates the use of ConnectionEndpointLocators to add Labels to a Connection:

以下代码演示了如何使用ConnectionEndpointLocator给一个连接加上标签

ConnectionEndpointLocator targetEndpointLocator =             new ConnectionEndpointLocator(c, true);targetEndpointLocator.setVDistance(15);Label targetMultiplicityLabel = new Label(”1..*”);c.add(targetMultiplicityLabel, targetEndpointLocator);ConnectionEndpointLocator sourceEndpointLocator =             new ConnectionEndpointLocator(c, false);sourceEndpointLocator.setVDistance(15);Label sourceMultiplicityLabel = new Label(”1″);c.add(sourceMultiplicityLabel, sourceEndpointLocator);

ConnectionEndpointLocator relationshipLocator =             new ConnectionEndpointLocator(c,true);relationshipLocator.setUDistance(30);relationshipLocator.setVDistance(-20);Label relationshipLabel = new Label(”contains”);c.add(relationshipLabel,relationshipLocator);


Adding Labels to the Connection

增加了标签的连接

Creating a Test Class

创建测试类

This class contains a main method that creates an SWT shell and places a Draw2d LightweightSystem on that shell. The LightweightSystem class provides the link between SWT and Draw2d. The test class creates a Draw2d figure to act as the contents of the LightweightSystem and adds two UMLClassFigures to this figure. It then connects the two class figures with a polyline connection, adds a diamond polygon decorator, and adds the UML relationship labels to the connection.

测试类包含了一个main方法来创建一个含有Draw2d LightweightSystem(LWS,用来连接SWT和Draw2d)的SWT Shell。例子使用Draw2d的Figure类作为LWS的内容,并在Figure上增加了两个UMLClassFigure。然后在两个图形间创建了一个带有菱形端点装饰和标签的连接。

This class uses the following images: { }. Download them and place them at the root of a Java project directory.

测试类使用了几个图片{ },请自行下载并放在java工程的根文件夹下。

import org.eclipse.draw2d.*;import org.eclipse.draw2d.geometry.PointList;import org.eclipse.draw2d.geometry.Rectangle;import org.eclipse.swt.SWT;import org.eclipse.swt.graphics.Font;import org.eclipse.swt.graphics.Image;import org.eclipse.swt.widgets.Display;import org.eclipse.swt.widgets.Shell;

/** * A test class to display a UMLFigure */public class UMLClassFigureTest { public static void main(String args[]){ Display d = new Display(); final Shell shell = new Shell(d); shell.setSize(400, 400); shell.setText(”UMLClassFigure Test”); LightweightSystem lws = new LightweightSystem(shell); Figure contents = new Figure(); XYLayout contentsLayout = new XYLayout(); contents.setLayoutManager(contentsLayout);

 Font classFont = new Font(null, “Arial”, 12, SWT.BOLD); Label classLabel1 = new Label(”Table”, new Image(d,   UMLClassFigureTest.class.getResourceAsStream(”class_obj.gif”))); classLabel1.setFont(classFont);

 Label classLabel2 = new Label(”Column”, new Image(d,          UMLClassFigureTest.class.getResourceAsStream(”class_obj.gif”))); classLabel2.setFont(classFont);

 final UMLClassFigure classFigure = new UMLClassFigure(classLabel1); final UMLClassFigure classFigure2 = new UMLClassFigure(classLabel2);

 Label attribute1 = new Label(”columns: Column[]”, new Image(d,   UMLClassFigure.class.getResourceAsStream(”field_private_obj.gif”))); Label attribute2 = new Label(”rows: Row[]”, new Image(d,   UMLClassFigure.class.getResourceAsStream(”field_private_obj.gif”))); Label attribute3 = new Label(”columnID: int”, new Image(d,   UMLClassFigure.class.getResourceAsStream(”field_private_obj.gif”))); Label attribute4 = new Label(”items: List”, new Image(d,   UMLClassFigure.class.getResourceAsStream(”field_private_obj.gif”)));

 classFigure.getAttributesCompartment().add(attribute1); classFigure.getAttributesCompartment().add(attribute2); classFigure2.getAttributesCompartment().add(attribute3); classFigure2.getAttributesCompartment().add(attribute4);

 Label method1 = new Label(”getColumns(): Column[]”, new Image(d,   UMLClassFigure.class.getResourceAsStream(”methpub_obj.gif”))); Label method2 = new Label(”getRows(): Row[]”, new Image(d,   UMLClassFigure.class.getResourceAsStream(”methpub_obj.gif”))); Label method3 = new Label(”getColumnID(): int”, new Image(d,   UMLClassFigure.class.getResourceAsStream(”methpub_obj.gif”))); Label method4 = new Label(”getItems(): List”, new Image(d,   UMLClassFigure.class.getResourceAsStream(”methpub_obj.gif”)));

 classFigure.getMethodsCompartment().add(method1); classFigure.getMethodsCompartment().add(method2); classFigure2.getMethodsCompartment().add(method3); classFigure2.getMethodsCompartment().add(method4);

 contentsLayout.setConstraint(classFigure, new Rectangle(10,10,-1,-1)); contentsLayout.setConstraint(classFigure2, new Rectangle(200, 200, -1, -1));

 /* Creating the connection */ PolylineConnection c = new PolylineConnection(); ChopboxAnchor sourceAnchor = new ChopboxAnchor(classFigure); ChopboxAnchor targetAnchor = new ChopboxAnchor(classFigure2); c.setSourceAnchor(sourceAnchor); c.setTargetAnchor(targetAnchor);

 /* Creating the decoration */ PolygonDecoration decoration = new PolygonDecoration(); PointList decorationPointList = new PointList(); decorationPointList.addPoint(0,0); decorationPointList.addPoint(-2,2); decorationPointList.addPoint(-4,0); decorationPointList.addPoint(-2,-2); decoration.setTemplate(decorationPointList); c.setSourceDecoration(decoration);

 /* Adding labels to the connection */ ConnectionEndpointLocator targetEndpointLocator =          new ConnectionEndpointLocator(c, true); targetEndpointLocator.setVDistance(15); Label targetMultiplicityLabel = new Label(”1..*”); c.add(targetMultiplicityLabel, targetEndpointLocator);

 ConnectionEndpointLocator sourceEndpointLocator =   new ConnectionEndpointLocator(c, false); sourceEndpointLocator.setVDistance(15); Label sourceMultiplicityLabel = new Label(”1″); c.add(sourceMultiplicityLabel, sourceEndpointLocator);

 ConnectionEndpointLocator relationshipLocator =   new ConnectionEndpointLocator(c,true); relationshipLocator.setUDistance(10); relationshipLocator.setVDistance(-20); Label relationshipLabel = new Label(”contains”); c.add(relationshipLabel,relationshipLocator);

 contents.add(classFigure); contents.add(classFigure2); contents.add(c);

 lws.setContents(contents); shell.open(); while (!shell.isDisposed())  while (!d.readAndDispatch())   d.sleep(); }}

Conclusions

结论

This article has served as an introduction to the customized use of the Graphical Editing Framework’s visual component, Draw2d figures. The concepts of Draw2d connections, decorations, and locators have also been introduced. For more information on GEF, see the GEF website. (http://www.eclipse.org/gef).

本文介绍了使用Graphical Editing Framework的可视化组件——Draw2d图形——的使用,同时也介绍了Draw2d连接、装饰、locator的概念。更多的信息请访问GEF主页(http://www.eclipse.org/gef

Acknowledgements

感谢

The author would like to thank Randy Hudson and Eric Bordeau for providing constructive comments on the article.

感谢Randy Hudson和Eric Bordeau为本文提供的建设性意见。

Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States, other countries, or both.

Technorati Tags: eclipse, draw2d, gef

内容概要:本文研究了基于DPWMA调制与正负序分离的ANPC三电平并网逆变器前馈控制策略,旨在解决传统三电平逆变器存在的谐波含量高、电网不平衡工况适应性差及动态响应速度不足等问题。通过采用有源中点箝位(ANPC)三电平逆变器拓扑,结合双极性倍频脉宽调制(DPWMA)、正负序分离锁相技术和电网电压前馈控制,构建了一套一体化的高性能并网控制体系。该体系不仅优化了逆变器的开关动作机制,改善了输出电压电流的谐波特性,而且通过精确的相位同步和扰动补偿,显著提高了系统的动态响应能力和抗扰性能。仿真结果显示,所提出的控制策略能有效降低并网谐波含量,提升锁相精度与系统动态稳定性,确保在复杂电网工况下的高质量稳定并网。 适合人群:具备一定电力电子基础知识和仿真技能的研发人员,尤其是从事新能源发电、储能系统、柔性输电等领域研究的专业人士。 使用场景及目标:①研究和开发高性能并网逆变器,特别是针对大功率、高电能质量要求的应用场景;②探索如何通过先进的调制和控制策略来提高并网逆变器对电网扰动的适应性和响应速度;③为相关领域的学术研究和技术开发提供理论依据和实践指导。 阅读建议:建议读者结合实际的仿真软件(如MATLAB/Simulink)进行实践操作,以便更好地理解和掌握文中提到的各种控制策略的具体实现方法。同时,鼓励读者关注最新的研究成果和发展趋势,不断深化对该领域的认识。
摘要 在全球生态环境问题日益严峻、公众环保参与意愿持续提升的背景下,传统环保志愿者招募与管理模式存在信息传播零散、供需对接不畅、管理效率低下等痛点,制约了环保公益事业的规模化发展。为解决上述问题,响应生态保护数字化发展需求,本课题设计实现“守望自然”环保志愿者招募与管理网站,通过数字化手段打通环保组织与志愿者的服务链路,对推动环保公益规范化、高效化发展具有重要的现实意义与实践价值。 该网站采用B/S架构与前后端分离模式开发,前端基于Vue架构建组件化响应式界面;后端以Java为开发语言,采用Spring Boot框架搭建应用,搭配MyBatis作为持久层框架,数据库选用MySQL并遵循第三范式设计7个以上核心数据表。系统涵盖用户与管理员两大核心角色,实现了闭环式环保志愿服务功能:用户端支持注册登录、个人信息管理、活动查询报名、环保知识学习、社区互动、问题反馈及客服咨询等功能,满足用户全流程参与需求;管理员端具备用户管理、用户审核、招募与活动信息发布管理、环保知识内容管理、问题反馈处理、证书模板管理、多维度数据可视化分析及社区内容监管等功能,全面支撑环保组织运营管理。开发过程中集成了Token身份认证、MD5密码加密、ECharts数据可视化等关键技术,融入活动智能推荐、数据驱动决策等创新设计,确保系统功能完备性与实用性。 经功能测试、性能测试及安全测试验证,系统运行稳定可靠,具有良好的易用性、安全性和可扩展性,能够高效满足环保组织的用户招募管理需求与用户的多元化参与需求,有效降低环保组织运营成本,提升用户参与体验,为环保理念传播与公益事业发展提供有力的数字化支撑。 关键词:环保志愿者;招募管理系统;Spring Boot;Vue;数据可视化
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值