SVG 图形编辑器的设计与实现
摘 要:为了揭示SVG图形编辑器的实现原理,本文将讨论图形绘制、数据缓冲区储存和SVG语句的生成等3个模块的实现方法,给出SVG编辑器实现的基本流程。
关键词:ArrayList类;SVG图形编辑器;Element接口
      SVG(Scalable Vector Graphic)是W3C组积开发的一种开放标准的文本式矢量图形标准语言,由于其具有莫大的优势,在业界将有一定的发展空间。当前,一些SVG的可视化编辑器已经陆续出现,例如SvgDeveloper,它是一款功能强大的SVG编辑软件,利用功能强大的绘制功能,可以绘制诸如圆形、矩形、星形等基本形状,也可以绘制文本、图像和自由曲线等复杂图形。同时,SvgDeveloper还提供了其他一些高级功能,可以更加容易的创建和管理SVG程序。下面简要说一下SVG图形编辑器实现的核心内容以及思想。
  一、功能需求与设计
  图形编辑器提供基本图形(直线、圆形、矩形以及文字等)直接绘制的机制,图形在创建后,可以通过相应机制,进行拖移操作,并且最终以SVG文件的形式输出。
  整个SVG图形编辑器分为3个功能模块,每个模块之间的耦合性比较强。第一部分为图形绘制模块,是整个系统的重要组成部分,直接应用于人机交互;第二部分为数据缓存机制模块,用于绘图后,对图形对象的储存,为生成SVG文件所必要的信息提供了来源;第三部分为SVG语句构建,采集相关图形信息,构建出SVG语句。这3个模块虽然功能上是独立的,但在实际实现过程中,它们的程序模块基本上是交集在一起的,是一个有机的统一体。
  二、 程序的实现
  1、绘图程序的功能简述
  本绘图程序主要是通过图元库完成圆形、椭形、矩形以及直线等图形的绘制,并可对这一系列图形进行可视化调整操作,如移动、拖放、修改等。
  2、绘图程序实现
  本绘图程序是运用JAVA高级程序编程语言编写的,因此开发程序之前必须对JAVA技术(特别是2D功能)有一个很好的理解。以下为绘图程序所涉及的图形概念描述:
  模型—视图—控制器(model-view-controller ,简称MVC)体系结构,该系统结构使用面向对象的设计原理将应用程序模块化,使其成为数据组件、表现组件以及输出组件。数据组件维护原始应用程序的数据,表现组件常常提供应用程序数据的可视表现,输出组件处理来自用户的输入等等。
  控制器实现了处理用户输入的逻辑。模型包含应用程序的数据,视图则生成模型数据的表现。当用户提供了一些输入时,控制器将根据给定的输入来修改模型(模型只包含原始的应用程序数据)。当模型改变时,它将变化通知给视图,于是视图可用改变后的数据更新其显示。字控制器中的视图可以一种特定的字体、合适的大小等属性将字符显示在屏幕上。
  JAVA的Swing组件是MVC的一个变形,它将视图和控制器结合在一个对象中,即成为代理的对象。代理对象既提供模型的表现,同时也提供了接口用于改变模型。例如,每个JButton组件有一个相关的ButtonModel,JButton就是该ButtonModel的代理。ButtonModel对象维护状态信息,如是否按下这个JButton组件,是否激活,以及维护一个ActionListener的列表。JButton组件提供图形表现,同时也修改ButtonModel的状态(如用户按下JButton时)。
  对于本绘图程序,先创建形状类的根接点MyShape类。MyShape类是一个抽象基类,其定
义了形状实体的基本接口和所有形状的公共方法的默认实现。图画中的每个形状实体都以独立的对象存在,而且是MyShape类的扩展。MyShape类的子类有:MyLine(直线)类,MyRectangle(矩形)类,MyOval(椭圆)类,MyText(文本)类等。
  3、处理用户输入机制
  创建图形的基本输入设备是鼠标。当用户通过鼠标进行按下、拖动以及放下等一系列操作的时候,新的形状实体就可在图画中得到创建或者改变状态。对于不同类型的MyShape子类,对鼠标事件的处理有着不同的要求。这里定义了抽象类MyShapeController,定义了MyShapeController子类共同的基本功能,其子类在创建过程中加入了相对应的细节。该抽象类负责响应鼠标事件,使用户能够将形状实体加入到图中。
  在类MyShapeController中,通过创建MouseListener,监听mousePressed以及mouseReleased事件,当用户按下鼠标按键时,通过调用startShape方法开始在鼠标按下的位置画一个新的形状实体。当鼠标松开的时候,调用endShape方法来完成当前的形状实体的绘制。当用户拖动鼠标时,也可通过MouseMotionListener调用modifyShape方法来修改当前绘制的形状实体。类MyShapeController中,使用了MouseAdapter和MouseMotionAdaper
的实例来响应MouseEvent。MouseAdapter类和MouseMotionAdaper类,作为适配器设计模式的例子,为对象提供了新的接口,使之能适应另一个对象的接口。
  4、拖放控制处理机制
svg实例  拖放控制处理机制,本编辑器采用DragAndDropController类的一个实例完成,用户可在图画内部和多文档界面的图画之间拖放特定的图形。DragAndDropController类通过实现3个接口来处理拖放操作:DragGestureListener、DragSourceListener和DropTargetListener。这些接口能使得DragAndDropController识别拖动的动作、DragSource事件和DropTarget事件。
    5、图形信息的储存
  由于本编辑器的输出是以SVG文件,所以必须对所绘制的图形相关的信息(类型,坐标等)进行科学的保存。
  现代信息技术为图形信息的储存提供的手段是多元化的。总体来说可以分为两大类:静态结构储存和动态结构储存。由于图块的储存信息是不等的,且当程序工作时,大图形包含图
块的个数也是不确定的,如果采取静态储存,就得先确定一个大结构数组去保存图形。但如果图形包含的图块比较少的情况下,就大大浪费了系统的资源,造成不必要的浪费,所以本编辑系统的图形信息储存采取的是动态储存结构。在本储存的模块中引入了ArrayList类,它是一个特殊的数组。ArrayList类具有以下优点:(1)支持自动改变大小的功能;(2)可以灵活的插入元素;(3)可以灵活的删除元素。                 
  ArrayList类的方法与属性:
  (1)构造器。ArrayList提供了3个构造器:public ArrayList( ), 默认的构造器,将会以默认(16)的大小来初始化内部的数组;public ArrayList(ICollection,用一个ICollection对象来构造,并将该集合的元素添加到ArrayList。public ArrayList(int),用指定的大小来初始化内部的数组。
(2)IsSynchronized属性和ArrayList.Synchronized方法。IsSynchronized属性指示当前的ArrayList实例是否支持线程同步,而ArrayList.Synchronized静态方法则会返回一个ArrayList的线程同步的封装。如果使用非线程同步的实例,那么在多线程访问的时候,需要自己手动调用lock来保持线程同步;当ArrayList为非线程包装的时候,SyncRoot属性其实就是它自己,
但是为了满足ICollection的SyncRoot定义,这里还是使用SyncRoot来保持源代码的规范性{list.Add(“Add a Item”); }如果使用ArrayList.Synchronized方法返回的实例,那么就不用考虑线程同步的问题,这个实例本身就是线程安全的,实际上ArrayList内部实现了一个保证线程同步的内部类,ArrayList.Synchronized返回的就是这个类的实例,它里面的每个属性都是用了lock关键字来保证线程同步。
  但是,使用这个方法(ArrayList.Synchronized)并不能保证枚举的同步,例如,一个线程正在删除或添加集合项,而另一个线程同时进行枚举,这时枚举将会抛出异常。所以,在枚举的时候,你必须明确使用SyncRoot锁定这个集合。
  6、图形信息的获取
  当需要获取保存在shapes( ArrayList的对象,用于保存MyShape对象)里的图形对象,则涉及到一个获取的过程。在这里我们可引入Iterator类,它提供了一个获取ArrayList对象所储存元素的接口。
  Iterator(迭代器)模式又称Cursor(游标)模式,用于提供一种方法顺序访问一个聚合对
象中各个元素,而又不需暴露该对象的内部表示。Iterator模式是运用于聚合对象的一种模式,通过运用该模式,使得我们可以在不知道对象内部表示的情况下,按照一定顺序(由iterator提供的方法)访问聚合对象中的各个元素。
    Iterator模式有如下重要的作用:
  (1)它支持以不同的方式遍历一个聚合,复杂的聚合可用多种方式进行遍历,如二叉树的遍历,可以采用前序、中序或后序遍历。迭代器模式使得改变遍历算法变得很容易,仅需用一个不同的迭代器的实例代替原先的实例即可,也可以自行定义迭代器的子类以支持新的遍历,或者可以在遍历中增加一些逻辑,如有条件的遍历等。 
  (2)迭代器简化了聚合的接口,有了迭代器的遍历接口,聚合本身就不再需要类似的遍历接口了,这样就简化了聚合的接口。
  (3)在同一个聚合上可以有多个遍历,每个迭代器保持它自己的遍历状态,因此你可以同时进行多个遍历。
  (4)Iterator模式可以为遍历不同的聚合结构(需拥有相同的基类)提供一个统一的接口,
即支持多态迭代。简单说来,迭代器模式也是Delegate原则的一个应用,它将对集合进行遍历的功能封装成独立的Iterator,不但简化了集合的接口,也使得修改、增加遍历方式变得简单。
  Iterator类的对象iterator可获取shapes所储存的对象,但其获取的信息只是图形对象(如MyLine、MyOval、MyText和MyRectangle),并不是对象所包含的元素信息(如line 、x1、fill、ellipse等),所以再由MyShape的方法getXML再进一步提取信息ArrayList对象shapes里储存所有对象的提取,但对于拖动操作来说,只需要抽取当前被选中的图形进行操作,这样Iterator类的对象iterator难以满足这个功能要求。在本模块中引入ListIterator类,它是Iterator类的一个子集,继承了Iterator类的所有的方法。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。