draw2d设计内幕之一:LightweightSystem设计和实现剖析
作者:余学锋 编辑:javamxj 发布:javamxj 源站点:分享Java快乐 这篇文章假设读者在浏览本章之前,已经对LightweightSystem有了一定的了解,基本上应该要明白LightweightSystem究竟是个什么?在 分享Java快乐 的 Draw2d专栏 中有关于LightweightSystem介绍的文章。在本文章中,提供了一个dxf文件解析器和dxf浏览器。dxf浏览器就是利用draw2d编写的。本文章力图言简意赅的解释与LightweightSystem相关的设计和实现,所以对一些基本的技术名词和术语并没有或没有详细的解释。 1. LightweightSystem设计和实现1.1 LightweightSystem设计
UpdateManager持有根图形元素的应用,因为只有通过根图形元素,才能够获取待更新的图形元素,请参见对根图形元素作用的描述。
EventDispatcher是一个抽象类,它为具体的事件分发器提供基本实现。SWTEventDispatcher是EventDispatcher类的具体实现。顾名思义,SWTEventDispatcher与SWT控件套件有关。draw2d的SDK文档是这样描述SWTEventDispatcher的:SWTEventDispatcher使draw2d具有分发SWT事件的能力;LightweightSystem增加SWT事件监听器到它的画布控件;当画布控件接受到一个SWT事件后,它就调用SWTEventDispatcher中定义的一个合适的分发器方法。在设计良好的图形系统中,自定义一套于平台无关的事件处理机制是一种通行的做法。Draw2d也不例外,在Draw2d中定义了与操作系统无关的事件序列,SWTEventDispatcher的主要职责之一就是要将来自于SWT的事件转换层draw2d中定义的内部事件,然后再将内部事件分发给恰当的图形元素。
可以LightweightSystem看成一个Canvas的适配器,它扩展了canvas的功能,并完全隐藏了与canvas的通信过程。可以直接将LightweightSystem看成一个拥有绘图表面、能够管理图形元素的绘制并处理各种用户交互事件的控件。 1.2 LightweightSystem实现
在LightweightSystem中定义了如下的变量:
private Canvas canvas; //充当绘图表面
IFigure contents; //需要在Canvas中显示的图形元素
private IFigure root; //LightweightSystem中的根元素
private EventDispatcher dispatcher; //事件分配器
private UpdateManager manager = new DeferredUpdateManager(); //更新管理器
private Rectangle oldControlSize = new Rectangle(); //画布控件的旧大小
除root外,其它几个图形元素外都比较容易理解。在前几篇文章中,已经对root的作用进行了描述,但为了保持文章的完整性,这里在重复一下对它的描述。根图形的职责如下: 1. 作为应用程序的背景。根图形元素完全覆盖在画布上,用户可以设置根图形元素的显示属性,改变根图形元素的显示属性就可以改变应用程序的背景。
2. 作为内容图形元素的父亲。
3. 作为搜索某个图形元素的搜索入口点。
4. 具备布局属性。因为它是内容图形元素的父亲,所以可以对内容图形元素进行布局。在当前的LightWeightSystem实现中,根图形元素的默认布局是堆叠布局(StackLayout)。
5. 通过绘制根图形元素中某个区域,可以绘制位置落在这个区域之内所有的图形元素。
应用程序不要期望重新定义LightWeightSystem中的根图形元素,这是不允许的。
实际上,从1.1节中的LightWeightSystem中的设计图中,比较容易理解LightWeightSystem为什么要定义这些变量。在某些可将设计转换成代码的CASE工具中,可以直接生成这些变量定义。
从LightWeightSystem的初始化过程中,可以对LightWeightSystem的逻辑结构有一个比较好的理解, · LightWeightSystem的初始化序列如下:
public LightWeightSystem(Canvas c)
{
//首先创建根图形元素并用该根图形元素初始化更新管理器和LightweightSystem对象的根图形元素。
RootFigure tmpRoot = createRootFigure();
GetUpdateManager().SetRoot( tmpRoot );
This.root = tmpRoot;
//更新管理器要更新图形元素时,需要一个具体的绘图上下文。为getUpdateManager设置图形上下文来源的目的就是
//告知更新管理器,当其执行更新时,如何获取图形上下文。通常,图形上下文是从控件中获取的。
canvas = c;
getUpdateManager().setGraphicsSource(new BufferedGraphicsSource(canvas));
//根据canvas的大小调整root图形元素的约束范围(使root与canvas的客户区一样大)
controlResized();
//接下来将LightweightSystem作为监听器注册到Canvas
addListeners();
}
· controlResized()方法方法体如下:
{
Rectangle r = new Rectangle(canvas.getClientArea());
r.setLocation(0, 0);
root.setBounds(r); //重新设置根图形元素的范围,使其大小等于画布控件的客户区大小,并完全覆盖在画布之上。
//使根图新元素重新有效,该调用会使根图新元素重新布局内容图形元素。
root.revalidate();
//通知更新管理器,更新根图形元素。
manager.performUpdate();
oldControlSize = r; //保存老的控件大小。
}
· addListeners()方法要负责将LightweightSystem对象作为监听器注册到Canvas中,该方法方法体如下:
protected void addListeners()
{
//首先创建一个事件处理器,这个事件处理器实现了许多的接口,这些接口中方法负责接受SWT的各种交互事件。
EventHandler handler = createEventHandler();
//处理辅助交互事件(为残疾人准备的)
canvas.getAccessible().addAccessibleListener(handler);
canvas.getAccessible().addAccessibleControlListener(handler);
//处理鼠标按下
canvas.addMouseListener(handler);
//处理鼠标移动等事件。
canvas.addMouseMoveListener(handler);
//处理鼠标跟踪事件。
canvas.addMouseTrackListener(handler);
//处理键盘事件。
canvas.addKeyListener(handler);
//处理遍历事件(模拟控件被遍历的情况)
canvas.addTraverseListener(handler);
//处理聚焦事件。
canvas.addFocusListener(handler);
//重新设置根图形元素的约束范围。
root.setBounds(oldControlSize);
//通知更新管理器,更新根图形元素。
getUpdateManager().performUpdate();
//初始化事件分发器。
setEventDispatcher(getEventDispatcher());
}
//GetEventDispatcher()函数体
protected EventDispatcher getEventDispatcher()
{
if (dispatcher == null)
dispatcher = new SWTEventDispatcher();
return dispatcher;
}
· EventHandler类(事件处理器)的定义
protected class EventHandler implements MouseMoveListener, MouseListener, AccessibleControlListener, KeyListener, TraverseListener, FocusListener, AccessibleListener, MouseTrackListener
{
…
}
在EventHandler类中的各个方法实现基本上都是直接调用getEventDispatcher().dispatchMouseMoved(event)分发事件。这个过程实际上就是,LightweightSystem接收SWT事件(通过EventHandler类事件的诸多接口方法),然后EventHandler再直接将事件转发到事件分发器中;然后事件分发器将swt事件转换成draw2d事件并分发到恰当的图形元素中。
通过对LightweightSystem类初始化过程的跟踪分析,基本上可以了解到组成LightweightSystem的各个部分是如何被创建的,更重要的是,通过跟踪分析,可以很清晰的了解到draw2d中事件的接收、分发过程。