Draw2D 繪圖-- UML 類圖

導讀:

  圖形編輯框架GEF有一個繪圖和佈局的插件叫Draw2D.Draw2D爲GEF應用程序提供繪畫和佈局管理功能。本文集中探討如何使用它去繪製一個簡單的UML類圖形。大多數應用程序使用GEF插件作爲編輯層。

  生成 Draw2d 圖形

  一個實例這篇文章的最終目的就是生成如下的一個圖形,它是一個簡單的UML類圖:

  classDiagGIF.gif

  

  設計圖形

  第一步就是要設計這個圖形要由哪些組件組成。

  在這個例子中,這個圖形可以由三個子圖形組成。(我們先設定這個圖形叫UMLClassFigure)。它的第一個子圖形: 一個Label 圖形,它用來顯示類的名稱這個例子中爲Table。第二個子圖形是一個容器去裝類的屬性和方法。爲這個目的,我們將設計一個圖形稱爲Compartment圖形。類和compartment圖形都是使用ToolbarLayout佈局去放置它們的子圖形。如同所示:

  UMLDiagGIF.gif

  

  創建 CompartmentFigure 類

  CompartmentFigur是被用來裝方法和屬性的。這個類繼承自org.eclipse.draw2d.Figure,使用ToolbarLayout佈局。而且它使用自定義的邊框。這個邊框是很簡單的頂部的黑色的1個象素,用來分隔其它的CompartmentFigures.它的代碼如下:

  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());

  }

  }

  }

  

  創建UMLClassFigure類

  

  UMLClassFigure類和前面的類在很多地方都相似。它包括3個子圖形------

  

  兩個CompartmentFigures分別裝屬性和方法,一個Draw2d Label顯示類的名稱。

  

  它同樣使用垂直的ToolbarLayout 佈局來放置它的子圖形。

  

  UMLClassFigure使用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;

  }

  }

  增加連接線

  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 sourceand the targetanchors. 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提供一個特殊類型的圖形,稱作連接,用來連接兩個圖形。在Draw2d中創建一個連接,第一步要做的是需要兩個端點。這些端點稱作源錨點和目的錨點。端點使用一個實現ConnectionAnchor接口對象來創建。一旦這些錨點被創建,它們通過調用connection對象的setSourceAnchor和setTargetAnchor方法被設置成端點。下面是使用ChopboxAnchor的實現。這個類型的錨點,能把connection的端點放到圖形的邊界上。

  PolylineConnection c = new PolylineConnection();

  ChopboxAnchor sourceAnchor = new ChopboxAnchor(classFigure);

  ChopboxAnchor targetAnchor = new ChopboxAnchor(classFigure2);

  c.setSourceAnchor(sourceAnchor);

  c.setTargetAnchor(targetAnchor);

  The following code demonstrates the addition of a connection:

  classDiagConnectionGIF.gif

  

  爲連接增加裝飾物

  Draw2d提供了端點的修飾,比如箭頭。在UML主題中,我們需要創建一個修飾物來表示一個對應關係。這將要使用到PolygonDecoration,它默認的形狀是一個被填充了的箭頭,但是你可以PointList創建新的修飾模板,然後調用PolygonDecoration的 setTemplate(PointList) 方法。

  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);

  classDiagDecoGIF.gif

  

  使用Locators爲連接增加Labels:

  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 constraint) 方法完成,constraint是一個實現了Locator接口的對象。Locator把圖形放置在連接上面。我們將使用這個技術來加入labels。我們使用ConnectionEndpointLocator 來放置這些lables。看它的名字就知道,這個locator把圖形放置在連接的端點附近。它允許使用者定義和端點之間的距離通過設置它自己的setUDistance(int)?和 setVDistance(int) 方法。(UDistance是連接本身和圖形的距離,vDistancs是圖形本身到連接的距離)。

  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);

  

  classDiagLabelsGIF.gif

  

  創建一個測試類

  這個類包含了一個main方法,產生一個SWT 的shell,放置一個Draw2 LightweightSystem到這個shell上。這個Lig類提供了LightweightSystem 提供了SWT和Draw2d直接的連接。這個測試類創建一個Draw2d圖形作爲LightweightSystem 的內容,並且爲這個圖形增加了兩個UMLClassFigures。然後它把這兩個類的圖形用一個polyline連接 連接起來,加入一個?diamond polygon 的裝飾器,並且加入了UML關係標籤。

  這個類使用如下圖片: { }. 下載它們並把它們放置到你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();

  }

  }



本文轉自

http://www.blogjava.net/aegeanllh/archive/2006/05/18/46876.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章