Draw2D教程.docx
- 文档编号:23867213
- 上传时间:2023-05-21
- 格式:DOCX
- 页数:29
- 大小:171.57KB
Draw2D教程.docx
《Draw2D教程.docx》由会员分享,可在线阅读,更多相关《Draw2D教程.docx(29页珍藏版)》请在冰豆网上搜索。
Draw2D教程
1、理解Draw2d
Draw2d是SWT平台上的图形库,你可以用它定制属于自己的、不依赖于特定操作系统本地组件的上层组件;
也可以用它开发基于图形的应用程序。
一般来说,基础代码编写者/GUI组件提供者们使用前一个功能,像译
者这样开发应用程序的人则使用后者更多一些。
Draw2d库依赖于SWT(不依赖JFace),提供了完整的图形应用程序开发包,使用它你几乎可以作出任意的
图形,但是除了简单的几何图形以外,任何图形都需要开发者自己手绘、或者用已有的图形进行组合;同时,
如果你想让你的图形响应各种事件(鼠标/键盘/拖拽等),也必须事事躬亲,显然自由的代价就是繁冗的代码
:
(。
本文从Draw2d的核心类及其方法讲起,然后理论结合实践,以一个flowchart(程序流程图)为例子进行实
战演习,同时会讲到拖拽(drag-and-drop,简写作dnd),以及如何使用Connector对象连接两个图形等。
1.1、使用Draw2d基础类
Draw2d在设计结构上有些类似SWT:
两者使用某些共同的类(确切说是Draw2d使用SWT的类);描绘(drawing)、
事件处理和组件的布局等机制都有相似的结构,对应如表C.1。
实际上,所有的Draw2dGUI必须都放在某个
SWTCanvas上。
Draw2d和SWT的第一个区别是:
在SWT中,一个Canvas用一个GC对象来提供绘图功能,但在
Draw2d中Canvas使用名为LightweightSystem的对象。
表C.1
LightweightSystem好比SWT中的Display,没有具体的形状,但是提供事件处理机制以及负责与外部环境
通信。
正如它的名字,LightweightSystem不依赖于特定操作系统,这意味着你失去了SWT/Jface重量级组件
的优势,比如快速的响应和本地外观风格,但你得到的,是对自己的组件的外观与行为的完全控制。
毫无疑问,Draw2d中最重要的类是Figure,你会看到,我们讲Draw2d,大部分是在讲它的方法以及子类。
就像SWT的组件都要放到一个Shell上一样,Figure必须放到LightweightSystem上以便显示。
如同SWT的Control
一样,Figure可以调整大小和位置,添加Listeners和LayoutManagers,以及设置颜色和字体。
同时,一个Figure
又相当于SWT中的一个Composite,可以在其上添加其他的Figure,即作为其他Figure的容器。
见图C.1。
图C.1
然而,不同于Control和Widget的是,你可以随心所欲地继承Figure。
Figure的图形可以绘制(drawing)
也可以使用图片。
Figure不仅可以使用单独的Listener接口,而且可以自己处理大部分事件;甚至可以发起某
些事件来唤醒GUI中的其他对象。
为了向Figure中加入图片或者进行手绘,你需要用到Graphics对象。
他就像SWT中的GC一样,提供了在一个给
定区域画图的方法。
Graphics类的很多方法和GC的完全一样,尤其是绘制线和几何图形、显示图片以及字体等方
面。
但Graphics还提供了一个不同于GC的功能:
它的对象可以在LightweightSystem中移动。
这意味着当你想要
改变一个图形组件的位置时,Draw2d提供了它自己的拖拽机制来将一个Figure移动到合适的位置。
1.2、Flowchart应用实例
我们的应用实例是一个程序流程图,如图C.2所示。
图C.2
Draw2d包含很多类和功能,在此无法一一详述,所以我们将只关注最主要的东西:
即前面提到的Figure及其 子类。
2、Draw2dFigures
构建一个Draw2dGUI需要写很多代码。
但是,区别于SWT/JFace的GUI元素,Draw2d的组件支持移动以及其他
各种操作,这些组件都是Figure的子类实例。
Figure的这些子类构成Draw2dGUI的可视部分。
图C.3列出了其中的
一部分子类,它们都是很重要的。
图C.3列出的子类普遍应用于我们的flowchart中,尤其是那些和Connection、Layer相关的。
但首先,我们需
要整体上介绍一下Figure。
图C.3
2.1、Figure的方法
如同SWT中的Control,Fgure类有许多方法来操作它的属性。
在这里我们不可能将其137个方法一一列举,但这
些方法大致可分为四类:
a操作Figure的可视部分
b事件处理
c跟踪parent和children
d管理图形
下面分别介绍一下这四类方法:
操作Figure的可视部分
这类方法和SWT是一样的。
包括设置Figure的bounds,location,size等参数,你可以控制Figure的最大/最小
尺寸、边框的大小、可视区域等。
还包括设置Figure的前景色背景色,焦点控制以及是否可见等。
Draw2d的事件处理
Draw2d事件处理过程也与SWT类似,但提供了一些新的events和listeners。
不同于SWT,Figure可以处理很多其
自己的事件。
所有的listeners和他们的处理方法列于表C.2:
表C.2
前5个addXXX方法与SWT的基本一样,addListener()可以接收无类型的事件。
最后三个则是Draw2d所特有的。
addAncestorListener()方法如同Swing的同名方法一样,响应该Figure的各级容器(祖先)的改变。
同样,方法
FigureListener响应Figure的移动事件。
最后一个,addPropertyChangeListener(),使得你可以定制自己的事件。
当你的Figure中的某个属性改变时,
手工调用此方法,则注册到该属性上的PropertyChangeListeners就会被唤醒。
Parent和childFigure
在SWT中,一个组件可以通过一个Composite放到另一个组件之上。
但在Draw2d的世界中,任何Figure都可以充
当其他Figure的容器。
所以Draw2d使用parent和child来代指容器Figure和其上的子Figure。
表C.3给出了创建这
种父子关系的方法:
表C.3
在SWT中,类似Button,Label这些组件是通过构造函数的参数来将自己加到一个Composite上的,但在Draw2d中,
则是由parent调用add()方法,将一个child加入,同时还可以跟一个参数,指明这个child的大小或者位置,以及
在childrenList中的次序。
ParentFigure可以通过getChildren()来取得所有的子图形,反之child则使用方法
getParent()来访问自己的父图形。
父图形还可以使用setChildrenEnabled()方法来启用/禁用某个子图形,或者
调用setConstraint()来移动子图形。
管理图形
尽管Draw2d提供了Graphics类来充当SWT中的GC角色(即绘图功能),但Figure还是有几个自己的绘图方法。
它
们不仅可以通过paint()方法来控制自身的显示,而且可以使用paintBorder()和paintClientArea()来选择显示哪
一部分。
Figure还可以用paintChildren()方法来控制children的显示,或者paintFigure()来只显示自身。
同时,
Figure还重载了几个类似SWT的repaint方法。
Draw2d还提供有确定用户鼠标选择区域的方法。
这不同于SWT,因为前者特别关注鼠标的精确位移,而后者只关心
用户选取了哪一个Control。
Figure的这些方法包括findMouseEventAt()和findFigureAt()等。
2.2、使用Labels和Clickbles
首先让我们来看一下Figure的子类中最简单的:
Label和Clickble。
这两种组件与SWT中的同名组件差不多,但是仍
有一些有趣的不同之处。
Lables
Draw2d的Label类似SWT的Label,但包含更多的方法来用作对文本以及对图片的定位。
例如,对于文本,可以用方法
getTextLocation()和getTextBounds()来测定其位置和大小。
同样,如果这个Label上有Image,那么可以使用方法
getIconBounds()和getIconAlignment()方法。
Clickables
Clickble包括Button和Toggle。
如同SWT的Button,可以使用style将其设置为toggle(即按下不会自动弹起的按钮
),checkbox,或者正常的push按钮。
你也可以控制它的状态,文本以及图片。
但Draw2d的Clickble和SWT的Button有
两个重要的不同:
第一、Clickble可以使用任意的Draw2dFigure;第二、Clickble的事件处理与SWT有所不同。
Draw2d用户界面一般来说比SWT/JFace的要更复杂些,所以,一个Clickble的状态信息由一个ButtonModel或者Togg
leModel对象来管理。
这样就分离了组件的行为和显示,使得我们容易分而治之。
你也可以把这些Model对象放在同一个
ButtonGroup里面,这样可以同时管理多个Clickble。
Clickble通过调用fireChangeEvent()方法来更新它的Model对象,就如同Figure利用firePropertyChangeEvent()
一样。
Clickble的属性常量定义在Modle类中,比如MOUSEOVER_PROPERTY和PRESSED_PROPERTY,当它们改变的时候
,Model就会发出一组Draw2d事件,或者通知它的ButtonGroup(默认)。
例程
列表C.1的代码不会在我们的flowchart中用到,但是它展示了Draw2d的Clickble,Model以及ButtonGroup如何一起
协作,在例程中我们使用了Clickble的子类CheckBox,然后给它设置了一个ToggleModel。
列表C.1:
Draw2D_Example,java
packagecom.swtjface.AppC;
importorg.eclipse.swt.widgets.*;
importorg.eclipse.draw2d.*;
importorg.eclipse.draw2d.Label;
importorg.eclipse.draw2d.geometry.*;
publicclassDraw2D_Example
{
publicstaticvoidmain(Stringargs[])
{
finalLabellabel=newLabel("Pressabutton!
");
Shellshell=newShell();
LightweightSystemlws=newLightweightSystem(shell);
Figureparent=newFigure();
parent.setLayoutManager(newXYLayout());
lws.setContents(parent);
Clickableabove=newCheckBox("I'mabove!
");
parent.add(above,newRectangle(10,10,80,20));
ButtonModelaModel=newToggleModel();
aModel.addChangeListener(newChangeListener()
{
publicvoidhandleStateChanged(ChangeEvente)
{
label.setText("Above");
}
});
above.setModel(aModel);
Clickablebelow=newCheckBox("I'mbelow!
");
parent.add(below,newRectangle(10,40,80,20));
ButtonModelbModel=newToggleModel();
bModel.addChangeListener(newChangeListener()
{
publicvoidhandleStateChanged(ChangeEvente)
{
label.setText("Below");
}
});
below.setModel(bModel);
ButtonGroupbGroup=newButtonGroup();
bGroup.add(aModel);
bGroup.add(bModel);
bGroup.setDefault(bModel);
parent.add(label,newRectangle(10,70,80,20));
shell.setSize(130,120);
shell.open();
shell.setText("Example");
Displaydisplay=Display.getDefault();
while(!
shell.isDisposed())
{
if(!
display.readAndDispatch())
display.sleep();
}
}
}
如你所见,Draw2d应用程序不过是一个SWT的Shell和一个LightweightSystem再加上Figures。
有一点很重要:
ChangeListern是在button的Model里,并且响应任何鼠标动作,包括点击和移过。
同时,因为两个Model都加到
了同一个ButtonGroup上,所以同一时间只有一个可以被选中。
为了让一个父图形能够“理解”子图形的一个Rectangleconstraint,你必须使用名为XYLayout的布局管理器
(LayoutManager)。
下面将讨论LayoutManager以及他们如何使得你控制Figure中的子图形的位置和大小
3、使用LayoutManagers和Panes
Layoutmanagers,就像SWT中的Layout类,用来描述子组件在容器中的位置和大小。
这一节将介绍LayoutManager
的子类,以及怎样使用它们。
另外,我们还会涉及Draw2d的panes。
ScrollPanes,LayerPanes,以及它们的子类。
Draw2d没有Composite类,
而这些pane一般就用来作为GUI的背景容器。
这些容器使得开发图形编辑器更加容易。
在这一节的最后,我们会继承
FreeformLayerdePane,创建flowchart工程的第一个Figure。
3.1、理解LayoutManager的子类
在SWT中,容器以来一个默认的布局策略来安排位于其上的组件;而在Draw2d中你需要选择一个LayoutManager的
子类,这些子类中,FlowFigureLayout和ScrollbarLayout只针对特定的Figure,我们将关注其他三个(表C.4)
表C.4
当一个父图形调用带有constraint参数的add()方法时给子图形指定位置时,由LayoutManager负责来“解释”这
个constraint并实际设置该子图形的位置。
我们将为我们的编辑器选择XYLayout。
现在我们需要一个合适的容器类:
我们选择LayeredPane。
3.2、LayeredPanes
由于Draw2d应用可能会很复杂,LayeredPane提供了很多“层”用来显示Figuer,使用透明的层(Layer),你可以将GUI分离成很多个面,不同的Layer有不同的特性,例如不同的LayoutManager。
这对我们的flowchart编辑器来说很重要,因为我们的图上不仅有Figure,还有Connection和feedback。
理解LayeredPane如何工作的第一步,是学习Layer。
Layer是透明的Figure,并包含两个属于它自己的方法:
containsPoint(),和findFigureAt()。
这些Layer都有固定的边界,但FreeformLayer可以向任意方向延伸,这对于那些有很大的图(大于窗口)的应用来说是必需的。
LayeredPane使用add()方法来加入新的Layer,方法参数指定Layer对象,一个用来识别它的key,以及一个index
来表明其位置。
当然你也可以从LayeredPane上删除一个Layer,或者改变它的index。
通过选用LayeredPane的子类,你还可获得更多的功能。
比如说,你想给你的pane添加缩放的功能,那么有ScalableLayeredPane,如果你想使得窗口向任意方向延伸,那么可以使用FreeformLayeredPane,如果两者都需要的话,可用ScalableFreeformLayeredPane。
在我们的flowchart中,我们只需要延伸功能;列表C.2的代码是用来作为我们最基本的编辑器的FreeformLayeredPane。
列表C.2:
ChartFigure.java
packagecom.swtjface.AppC;
importorg.eclipse.draw2d.*;
publicclassChartFigureextendsFreeformLayeredPane
{
publicChartFigure()
{
setLayoutManager(newFreeformLayout());
setBorder(newMarginBorder(5));
setBackgroundColor(ColorConstants.white);
setOpaque(true);
}
}
在以上代码中,我们为FreeformLayeredPane设置了外观属性,但到目前为止尚未加入任何Layer,后续章节将完成这个任务。
3.3、ScrollPanes与Viewports
ScrollPane可以加在任何的Figuer上,为其提供滚动条的功能。
并且可以设置滚动条为始终可见、始终不可见,或
者在需要的时候才出现。
在任何一个给定时刻,只有ScrollPane的一部分可以被看见,这个可见的区域称为Viewport。
他们类似于Layers但
提供了更多方法来控制大小和形状。
现在,我们已经有了flowchart最底层的容器,我们需要创建各种图形加到这个容器上面来。
为此,我们得研究一下
Draw2d的Graphics类,以及它的绘图功能。
4、使用Graphics来创建图形
在SWT中,graphiccontext(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
packagecom.swtjface.AppC;
importorg.eclipse.draw2d.*;
importorg.eclipse.draw2d.geometry.*;
publicclassDecisionFigureextendsActivityFigure
{
FixedAnchorinAnchor,yesAnchor,noAnchor;
publicDecisionFigure()
{
inAnchor=newFixedAnchor(this);
inAnchor.place=newPoint(1,0);
targetAnchors.put("in_dec",inAnchor);
noAnchor=newFixedAnchor(this);
noAnchor.place=newPoint(2,1);
sourceAnchors.put("no",noAnchor);
yesAnchor=newFixedAnchor(this);
yesAnchor.place=newPoint(1,2);
sourceAnchors.put("yes",yesAnchor);
}
publicvoidpaintFigure(Graphicsg)
{
Rectangler=bounds;
PointListpl=newPointList(4);
pl.addPoint(r.x+r.wid
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- Draw2D 教程