JCad:使用Swin岁Java2。开发矢量图形应用程序
王挺昊
摘 要:本文结合作者开发的CAD程序JCad介绍了利用Swing及Java2D开发矢量图形应
用程序的方法.使用该方法不但大大简化了应用程序的开发复杂度,同时更可以充分 Java2D
及 Swing的一些良好特性使应用程序达到更好的可扩展性,可集成性,可移植性.同时,本文
具体介绍了整个程序的从分析到实现的过程,并对该过程电的若干具体问题做了讨论
关键字:Swing, Java 2D,Vector-based Graphics
传统的矢量图形应用程序主要使用依赖于 Win32API,Xlib等 GUI工具提供的简单绘图
功能,如画线,画圆等。这些功能对一个完整的矢量图形应用程序是远远不够的,现有的软
件多是自己进行了大量的工作对绘图功能进行扩充,同时 GUI工具提供的绘图功能多采用
函数调用的形式,即使用输入参数 (如点坐标等)进行函数调用的形式,这样在消息循环的
更新函数中需要调用大量的绘图数据并大量地进行函数调用。这样的方式对于整个程序的结
构和设计模式都具有较大地负面影响。
Swing/Java2D API及Gnome/GnomeCanvas[9]等新一代GUl类库出现彻底改变了这一状
况,不但提供了强大的绘图功能,同时实现了一套全新的绘图模式。本文对 Java2D 的设计
思想和绘图模式做一简单介绍,后结合开发实际,介绍了利用 Java2DlSwing开发一完整的
工程图绘制系统((2D CAD)的程序结构,设计模式及具体实现。最后,对开发过程中遇到的
问题和对使用Java2D API/Swing的体会作一总结和讨论。
1. Java2D API简介及与传统绘图API的比较
Java2D API是Sun公司在Java2中提供了的绘图API,与awt紧密结合,不但可以完成复杂图
形及图象的绘制,更体现了全新的设计思想,下面我们通过一简单绘图过程对 Java2D 及传
统的绘图API〔以MFC为例)做一简单比较,在MFC中整个绘图过程通过对CDC类的成
员函数的调用来实现,如我们需要绘制一最简单直线及一圆弧,需要使用MoveTo和LineTo
两个函数,应用如下代码段
Void CmyView:inito
{
x一乡’
X I一 ‘。。
}
void CMyvew::OnDraw(CDC" PDC)
PDC->MoveTo(0,0);
!
t
.
.
l
es
u
卜
!
L
卜
卜
.
r
f
f
.L
豁
卜
f
.
卜
1
七
卜
勺
卜
杭
找
洲
卜
协
卜
峪
J
卜
卜
pDC->LineTo(xl,x2);
pDC->Arc(.......... );11G个参数
}
个绘制参数,并调用三个不同的函数来完成绘制过程。
这样我们需要在绘制前中设定8
View的分离,所有图形的绘制都只通过对Graphics2D对象
而在 Java2D中实现了Model与
的成员函数 draw·的调用来实现,应用程序只要建立图形对象并实现(implements)Shape接口
既可在paint(awt Component)或paintComponent(SwingComponent)中通过对draw的调用来完
成各种各样的图形绘制。使用Java2D API完成相应的功能代码如下
Line2D line;
Arc2D arc;
void initQ
{
line = new Line2D(0,0,xl,yl);
arc = new Arc2D(.);
)
void paintComponent(Graphics g)
笼
Graphics2D G2=(Graphics2D)g;
G2.draw(line);
G2.draw(arc);
}
这样我们只需要在绘制前建立两个对象即可
形需要绘制,我们只需使用Array或LinkedList
Iterator来反复调用同一 draw方法即可完成。
要自己设计相应的类并实现Shape接口即可。
一个对象。由这个简单的例子我们可以看到
,同时设想如果我们有大量的各种各样的图
等对象来保存这些图形对象,我们只要使用
再设想我们如果需要绘制更复杂的实体,只需
再进一步,我们可以将整个矢量图形设计成为
Java2D不但提供了易用的接口,还提供了一个
.这样我们可以通过对该框架的扩展来实现我们需要
可扩展的绘图系统的框架(FrameWork)
的几乎任何图形的绘制功能
由上面的简单例子我们可以看到,
Java2D API的设计思想与
是通过框架的设计实现了Model,View,Control的分离,为整个API的扩展性,FUMITNWN
的易读性打下了良好的基础。同时,Java2D还提供了图形变换,图象处理,字体(Text),SVG
输出等一些强大功能。这些特征及功能也是当前桌面应用程序和GUI的发展方向.
2.现有解决方案简介
当前市场上流行的工程图绘制解决方案的开发多开始于七八十年代
是利用 Win32APi或 Xlib等底层 GUI库进行了大量的封装工作后形成,
,主要的技术路线
商业解决方案主要
拜一— 一蘸颧潺撇毅
有Autodesk公司的AutoCAD和Bentley公司的Microstation。以上软件多成型于八十年代,
主要采用C/C++语言编写。经过长时间的发展完善,功能已很强大,使用也非常方便,但从
现在看来。主要有以下一些不足:
. 移植较差,由于以上解决方案多依赖于特定平台的 GUI库,进行跨平台移植将很
困难或根本不可能,如AutoCAD基于MFC类库,只可以在 Windows平台上运行。
. 可集成性差,信息技术的迅速发展使应用程序的可集成性成为一个重要因素,而
由于以上的商业解决方案的技术路线较陈旧,添加基本的网络和数据库支持均不
方便,进一步通过CORBA等进行集成也十分困难。
. 开放性不佳且开发成本过高,使用专门的数据格式。开发接口,甚至 GUI界面,
用户使用或进行二次开发需要学习相应的专用的界面及开发库。
开放软件的解决方案有QCad[5],freedraft[7],主要采用C什语言编写,虽然部分克服了商业解
决方案的开放性问题,但并未解决以上所述的其他局限性。而且,由于工作量问题,这些方
案在界面和易用性方面并不如人意。
以上的一些弱点,成为现有解决方案继续发展的瓶颈。
3. JCad简介
由于Java的先天优势,如利用Java 2D/Swing等技术实现一2D CAD系统,以上问题即
可迎刃而解。于是作者便萌生了利用Java 2D/Swing实现一2D CAD系统(JCad[8])的想法。
首先,由于Java的”write once, run anywhere'特性使得JCad能够在几乎所有的平台上运行并
保持对用户保持一致。其次,使用进行数据库网络的连接或提供CORBA等接口都非常方便。
Swing的强大功能使得友好的拥护界面的创建变的较容易。最后,Java平台良好的体系结构
将为该项 目的可扩展性,可维护性,打下良好的基础。
同时,JCad主要使用通过和开放的标准。如DXF,SVG等,并以开放源码的形式提供了
最大的开放性。目前,该项目基本结构和功能已完成,正在完善之中。
4.系统设计及实现
通过对现有解决方案的考察和对发展趋势的分析。该系统应能完成以下的基本功能为
工程图的编辑。同时应具有如下的特性:
.
.
…
使用 100% Pure Java及Swing及】ava2D API.
支持DXF格式文件的输入输出及HPGL,SVG,EPS等矢量文件格式的输出
用户可方便地进行工程图绘制其其他扩展功能
所有操作通过一统一界面提供,用户无须使用命令行或进行模式转换
具有良好的可扩展性,提供多种方式 ((jar classscript )以方便用户定制或添加功能
由以上所述并参考「21中的经验,JCad的类结构可简单描述如下:
—
一一 礴
从撇蘸睦摇夔戳翻川_
r
食
t
毯
膝
蛋
曹
蛋
蛋
阵
甚
玲
份
昔
‘
‘
落
玲
r
答
思
苍
荟
健
1!
1
奋德喂套‘tl
冬
雀
‘
腹
卜
卜
L
‘有t
旅卜
套
!
1
艰‘
异
t
‘
t
‘币
r
.
夕
图一 JCad结构设计
如上图所示,JCad类包含了该程序的main入口及用户界面构建代码,而JCadGraph接口
保存了工程图中的所有信息。包括所有绘图元素,层、线形等信息。而不同格式的文件只需
要继承该接口并实现相应的方法即可,为系统的可扩展性打下了良好的基础。所有图元均采
用了Java 2D的统一Shape接口,这样既可以直接使用Java 2D提供的Line2D,Arc2D等图形
对象,又可以通过对该Shape接口的实现提供新的图形对象或更高级的图形对象。
JCad中的所有操作都通过继承Swing的AbstractAction实现,放入一个数组中保存,通
过 ActionName可以获得相应的Action,从而可以实现界面的动态创建,即程序界面可通过资
源文件来配置。
此外,Listener的机制也为处理鼠标事件提供了很大的方便,简化了动态捕捉等复杂功
能的实现。也为各种不同功能模块的分离奠定了良好的基础。
目前该项目已实现了基本的图元绘制和修改等功能,其他功能正在完善之中下图为JCad
界面
图二 JCad程序界面
5. 实现中的其他问题及讨论
撤消I重做 (Undo/Redo)支持,实现 Undo/Red。是桌面程序的基本功能之一,一般实
现的方法是通过将所有的操作对象化并存储在一 LIFO栈中,通过栈指针的移动实现,具体
原理在[[3】中有详细论述,Swing通过提供一系列的对象及接口提供了对 Undo/Red。的支持,
这样大大方便了桌面程序的开发。
具体使用方法为在程序中放置一唯一的 UndoManager对象,将各种操作通过实现
UndoableEdit接口进行对象化。在进行可撤消的操作后将该操作的对象放入 UndoManager
对象后即可通过对UndoManager相应方法的调用实现Undo/Red。功能。
Java2通过 ResourceBundle的方法实现了 il 8n支持,只要提供了不同Locale下的资源
文件,Java2会根据用户不同的 Locale来使用相应的资源文件。但 Java中所有的字符都是
采用 Unicode,所以对于中文来说需要在资源文件输入 Unicode编码。这样对开发者来说有
一些不便 。
同时Swing对消息的处理采用Listener接口的方式,对开发者来说非常方便且直观,避
免了采用消息分派或相应方式所带来的开发的复杂性。
Script功能正通过jpython进行实现。
综上所述,在开发 JCad的过程中,笔者体会到了Java2的诸多优点,个人认为 Swing
及 Java2D确实代表了今后图形桌面应用的发展方向。仅从代码长度来看,通过与相似的解
决方案[41的比较。一般来说,实现同样的功能,使用 Java2要比使用 C++(QT)代码长度少
50% a
目前,JCad的运行效率比使用 C++的解决方案要低一些,将来随着优化算法的增加和
整个硬件性能的提高将会得到解决。
参考资料:
[1] J. M. VLISSIDES,M. A. LINTON: Unidraw: A Framework for Building Domain-Specific Graphical
Editors ACM Transactions on Information Systems, Vol. 8, No. 3, July 1990
冈
[31
Mark Priestley: Practical Object-Oriented Design with UML McGraw-Hill Companies,lnc.
Erich Gamma Richard Helm Ralph Johnson John Vlissides设计模式一可复用面向对象软杯的基础机
械工业出版社
[4]伍样生,王克宏 java 2D API技术及其实现方法 中国图象图形学报19”年。8期
[5] Andrew Munstun The Ocad Project bpp:Ilwww.Qcsd.ore
[6] The Jpython group The Jpython Project [ntp-llwwwip ho ora
闭 The freedraft group The freedraft Project htto-lAvwwfreeeneineer.ore
田 Wang Tinghao The JCad Project b9parcad.enuchinaore
侧 The Gnome .myp叫 The Gnome卫r41=曲tr叨:^;^w gnome.ore
33吕
几 一1 下下甲一翼藐{酬熬 }薪万 下
食
畜
蕉
蛋
哇
.
卫
谁
旅
甚
膝
崔
崖
.
.
.
腾
‘
耀
万
形
膝
‘
嘴
1
‘
争
,
f
‘
峻
睡
感
‘
‘
.
‘
暇
‘
阵
r!
t
t
慈
f
f
‘
‘
于
t
解
毛
!
t
卜
仁
阵
‘!
‘卜‘肠...
卜
1
百
.!
诊.
少