Draw2D 教程(四)

王朝other·作者佚名  2007-05-29
窄屏简体版  字體: |||超大  

4、使用Graphics来创建图形

在SWT中,graphic context(GC)可以单独创建为一个对象,也可以通过PaintEvent获得。但是在Draw2d中,Figure

可以从2.1节中讲述的那些paint方法中获得Graphics(方法参数)。Graphics的绝大多数方法都和CG中的相同,最大

的不同是Draw2d允许Graphics对象利用translate()方法移动。

然而,Draw2d提供了更为强大的功能来创建和操纵几何图形(Shapes)。它有好几个包、很多类用来处理几何图形。

4.1、使用Graphics类

如前所述,Graphics类的方法和SWT的GC基本一样,所以,在这一小节里,我们将创建图C.2种列出的那些组件,即

如下三种Figure:

1)DecisionFigure——即程序流程图中的分支结构,一个输入,两个输出(是/否)。

2)ProcessFigure——流程图中的某个处理,一个输入,一个输出。

3)TerminatorFigure——表示一个程序流程的开始或者结束,只有一个输入(结束)或输出(开始)。

对于我们的以上三种Figure,他们的大小由一个叫做size的变量来控制,他们上面显示的文字由一个叫做message

的String来设置。这些限制都来自于Figure对象的外部,所以暂时你还看不到。

这些类的代码如下:(列表C.3至C.5)

列表C.3:DecisionFigure.java

package com.swtjface.AppC;

import org.eclipse.draw2d.*;

import org.eclipse.draw2d.geometry.*;

public class DecisionFigure extends ActivityFigure

{

FixedAnchor inAnchor, yesAnchor, noAnchor;

public DecisionFigure()

{

inAnchor = new FixedAnchor(this);

inAnchor.place = new Point(1, 0);

targetAnchors.put("in_dec",inAnchor);

noAnchor = new FixedAnchor(this);

noAnchor.place = new Point(2, 1);

sourceAnchors.put("no",noAnchor);

yesAnchor = new FixedAnchor(this);

yesAnchor.place = new Point(1, 2);

sourceAnchors.put("yes",yesAnchor);

}

public void paintFigure(Graphics g)

{

Rectangle r = bounds;

PointList pl = new PointList(4);

pl.addPoint(r.x + r.width/2, r.y);

pl.addPoint(r.x, r.y + r.height/2);

pl.addPoint(r.x + r.width/2, r.y + r.height-1);

pl.addPoint(r.x + r.width, r.y + r.height/2);

g.drawPolygon(pl);

g.drawText(message, r.x+r.width/4+5, r.y+3*r.height/8);

g.drawText("N", r.x+7*r.width/8, r.y+3*r.height/8);

g.drawText("Y", r.x+r.width/2-2, r.y+3*r.height/4);

}

}

由于分支结构不是规则图形(它是个棱形),无法使用既有图形,所以我们需要指定一系列点来描绘它;谢天谢地,

ProcessFigure是一个矩形(Rectangle),所以容易创建地多。

列表C.4:ProcessFigure.java

package com.swtjface.AppC;

import org.eclipse.draw2d.*;

import org.eclipse.draw2d.geometry.*;

public class ProcessFigure extends ActivityFigure

{

FixedAnchor inAnchor, outAnchor;

public ProcessFigure()

{

inAnchor = new FixedAnchor(this);

inAnchor.place = new Point(1, 0);

targetAnchors.put("in_proc", inAnchor);

outAnchor = new FixedAnchor(this);

outAnchor.place = new Point(1, 2);

sourceAnchors.put("out_proc", outAnchor);

}

public void paintFigure(Graphics g)

{

Rectangle r = bounds;

g.drawText(message, r.x + r.width/4, r.y + r.height/4);

g.drawRectangle(r.x, r.y, r.width-1, r.height-1);

}

}

TerminatorFigure的左右两条边是圆弧,所以比ProcessFigure要麻烦点,但代码却是不难理解的。

列表C.5:TerminatorFigure.java

package com.swtjface.AppC;

import org.eclipse.draw2d.*;

import org.eclipse.draw2d.geometry.*;

public class TerminatorFigure extends ActivityFigure

{

FixedAnchor inAnchor, outAnchor;

public TerminatorFigure()

{

inAnchor = new FixedAnchor(this);

inAnchor.place = new Point(1, 0);

targetAnchors.put("in_term",inAnchor);

outAnchor = new FixedAnchor(this);

outAnchor.place = new Point(1, 2);

sourceAnchors.put("out_term",outAnchor);

}

public void paintFigure(Graphics g)

{

Rectangle r = bounds;

g.drawArc(r.x + r.width/8, r.y, r.width/4, r.height-1, 90, 180);

g.drawLine(r.x + r.width/4, r.y, r.x + 3*r.width/4, r.y);

g.drawLine(r.x + r.width/4, r.y + r.height-1, r.x + 3*r.width/4,

r.y + r.height-1);

g.drawArc(r.x + 5*r.width/8, r.y, r.width/4, r.height-1, 270, 180);

g.drawText(message, r.x+3*r.width/8, r.y+r.height/8);

}

}

显然,这些类不会只负责将图形画出来就完事了,还有两个更复杂的方面:一是这些Figure需要连接到其他的Figure

上去,这需要使用ConnectionAnchors(叫做FixedAnchors)。第二,这些图形将来在讲述GEF的时候还要用到,很

多方法现在解释还为时过早(作者这里主要指拖拽、编辑上面的文字等功能)。

由于所有这三个类都继承了ActivityFigure,所以现在该它登场了。这个基类包含上述三个Figure的共性。如列表

C.6所示,他的大部分方法用来跟踪Connections以及Connections的anchors。

列表C.6:ActivityFigure.java

package com.swtjface.AppC;

import org.eclipse.draw2d.*;

import org.eclipse.draw2d.geometry.*;

import java.util.*;

abstract public class ActivityFigure

extends Figure

{

Rectangle r = new Rectangle();

Hashtable targetAnchors = new Hashtable();

Hashtable sourceAnchors = new Hashtable();

String message = new String();

public void setName(String msg)

{

message = msg;

repaint();

}

public ConnectionAnchor ConnectionAnchorAt(Point p)

{

ConnectionAnchor closest = null;

long min = Long.MAX_VALUE;

Hashtable conn = getSourceConnectionAnchors();

conn.putAll(getTargetConnectionAnchors());

Enumeration e = conn.elements();

while (e.hasMoreElements())

{

ConnectionAnchor c = (ConnectionAnchor) e.nextElement();

Point p2 = c.getLocation(null);

long d = p.getDistance2(p2);

if (d < min)

{

min = d;

closest = c;

}

}

return closest;

}

public ConnectionAnchor getSourceConnectionAnchor(String name)

{

return (ConnectionAnchor)sourceAnchors.get(name);

}

public ConnectionAnchor getTargetConnectionAnchor(String name)

{

return (ConnectionAnchor)targetAnchors.get(name);

}

public String getSourceAnchorName(ConnectionAnchor c)

{

Enumeration enum = sourceAnchors.keys();

String name;

while (enum.hasMoreElements())

{

name = (String)enum.nextElement();

if (sourceAnchors.get(name).equals(c))

return name;

}

return null;

}

public String getTargetAnchorName(ConnectionAnchor c)

{

Enumeration enum = targetAnchors.keys();

String name = null;

while (enum.hasMoreElements())

{

name = (String)enum.nextElement();

if (targetAnchors.get(name).equals(c))

return name;

}

return null;

}

public ConnectionAnchor getSourceConnectionAnchorAt(Point p)

{

ConnectionAnchor closest = null;

long min = Long.MAX_VALUE;

Enumeration e = getSourceConnectionAnchors().elements();

while (e.hasMoreElements())

{

ConnectionAnchor c = (ConnectionAnchor) e.nextElement();

Point p2 = c.getLocation(null);

long d = p.getDistance2(p2);

if (d < min)

{

min = d;

closest = c;

}

}

return closest;

}

public Hashtable getSourceConnectionAnchors()

{

return sourceAnchors;

}

public ConnectionAnchor getTargetConnectionAnchorAt(Point p)

{

ConnectionAnchor closest = null;

long min = Long.MAX_VALUE;

Enumeration e = getTargetConnectionAnchors().elements();

while (e.hasMoreElements())

{

ConnectionAnchor c = (ConnectionAnchor) e.nextElement();

Point p2 = c.getLocation(null);

long d = p.getDistance2(p2);

if (d < min)

{

min = d;

closest = c;

}

}

return closest;

}

public Hashtable getTargetConnectionAnchors()

{

return targetAnchors;

}

}

对于ConnectionAnchor和Connection,我们将稍后再讨论。现在让我们看一下Draw2d的几何包。

4.2、Draw2d中的几何和图论

你已经看过如何使用Point和Rectangle,但Draw2d还提供了其他更多的类来处理几何图形。例如更高精度的类

PrecisionPoint,PrecisionRectangle,以及PrecisionDimension。此外还有Ray对象,其作用就像数学中的向量

一样;以及Transform类,用来实现移动、旋转、缩放等功能。

包org.eclipse.draw2d.graph里面有一些用来创建和分析有向图的工具类,例如基本的Node和Edge,以及特有的

布局管理器DirectedGraphLayout。图论已远超本书范围,但如果你对此有兴趣,这个包应该是很有用的。

Draw2d的Figure之间并非是用Edge连接的,而是用Connection,下面来讨论这个类。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
 
 
© 2005- 王朝網路 版權所有 導航