GEF draw2d 学习随笔

更新有两种情况引起,A.是承载图形的控件容器在被损毁时触发,称为系统重绘;

              B.二是图形系统由于绘制需要在内部调用更新,称为程序重绘。

情况A

    1、它是AWT在操作系统事件作用下要求重绘的,表现为主动,因为它是图形系统承载体,皮之不存毛之焉附?

       所以重绘是必须的。

    2、重绘时要取得控件损毁区域作为剪裁区绘画所有图形,这样在剪裁区之外的图形部分将不被绘制,

       GRAPHICS已优化了剪裁绘画的功能,graphics在绘画前会计算所有要被绘画的图形是否在剪裁区内,

       如果不在则不绘制,如果完全在其内则绘制,如果相交就绘被包容的部分。

    3、由于剪裁区已优化了性能,如果再把剪裁区作为缓冲图片,性能会更好,所以不需要再计算与剪裁区

       相交的图形,而特别针对这些相交图形重绘了,可以重绘所有图形,这样的计算损耗其实跟前者差不多,

       不然draw2d一定会采用前者,但实际上draw2d是在剪裁区内重绘所有图形。

    4DRAW2D系统重绘过程:

       a.系统事件paint触发LWS.paint方法,该方法调用updateManager.paint方法

       b.系统事件resize触发LWS.controlResize方法,该方法调用updateManager.performValidate方法。

       c.系统事件resize的调用必定触发事件paint,以上ab是不是执行了两次重绘呢?

         答案肯定不是,但现在还没看懂。但controlResize除了重绘之外,还要调整根图形的客户区及座标。

 

 

情况B

    1、由程序指定要更新的图形或区域,对于系统来说是被动晌应。

    2、程序重绘是窗口区没有破坏,但在下列因素下却必须重绘:某图形移动、删除、绘画过程、缩放等,

       由于它的改变,会牵涉一系统图形改变,那么就需要重绘,特别是图形的移动,辅助图形每步都要擦旧绘新,

       重绘频率很高。

    3、程序重绘也采用剪裁区,该剪裁区由增量计算脏区域而得,脏区域可由调用产生也可由无效图形区域而得。

       这点跟情况A一样,在剪裁区内重绘所有图形,并使用缓冲重绘。

    4DRAW2D程序重绘过程:

       a.图形调用重绘方法:validateinvalidate,revalidate,repaintrepaint方法是直接报告脏区域

         revalidate先使图形到父级无效并报告诉无效图形;validate设图形有效并调用排版;invalidate

         使图形无效并使排版也无效。

       b.updatemanager报告脏区域或无效图形最终均导致performUpdate方法的调用(在之前使用了线程池),

         performUpdate方法先firevalidating,这个事件只有figurecanvas视口感兴趣并导致内容对象重新排版,

         所有图形有效化,图形有效化导致要重新排版,排版会导致报告脏区域。

         接着就是调用repaireDemage修补损毁区。该方法过程如下:

         1.合并脏区域得剪裁区;2.用缓冲笔在剪裁区内画所有图形;3.releaseGraphics方法内调用

           griphicsSourceflush方法,在控件内画出缓冲图片。

          

graphicsSource作缓冲绘制,getGraphics分配缓冲图片并获取缓冲图片大小的graphics对象,rander是将缓冲图片输出并释放。

在绘画时,必须调用一次getGraphicsrander一次,分配一次缓冲不能用多次,因为rander在调用后会释放缓冲

          

更新的无效图形被重绘的过程分析

    前面谈的是脏区域的更新,有两个方法均可增加脏区域,一个是updateManage#addDirtyRegion一个是IFigure#repaint而后者是调用了前者,现在有个问题,无效图形列表是如何变成脏区域而被更新的呢?为什么在updateManager内不直接将无效图形列表转为脏区域从而实现更新呢?答案是要考虑排版的问题,排版会使图形变形和移位,给用户呈现自动合理的自动布局观感 ,所以这个转换是间接的,而且和前面这两个方法相关,下面的过程描述看过既可明白。

1、  界面晌应,在调用IFigure#setborder, setContstraint()setLayoutManager()add()remove()等,会自动调用revalidate()方法

2、  Revalidate方法使上链图形和布局的persize无效并将根图形增加到无效图形列表

3、  在向无效图形列表增加无效图形时,触发updateManager线程执行performUpdate

4、  performUpdate执行图形有效化和修补图形。在有效化过程中,执行无效列表内图形的validate方法。

5、  IFigure#validate调用本图形的布局对象

6、  布局对象的layout先使所包含的所有图形无效,并根椐现有图形的合适大小为图形分配合适大小(persize)并调用每个图形的setBounds方法重新给图形定位和大小。

7、  IFigure#setBounds调用repaint方法从而完成整个链条。

 

 

    JAVA窗体坐标是相对于桌面的,即win.getLocation得窗体在桌面位置,而窗体控件是相对于窗体的。

    所以必须在graphicsSource获取graphics前平移到正确位置

          

         

缓冲使用效果:界面不保持显示状态不变,图形在迅速绘画到缓冲位图中,只在画完后执行对缓冲位图的绘画,画缓冲位图才会导致屏幕更新,

而画一个位图速度很快,何况这个位图缩小到只是被损损坏的区域,一般几百K而已,用户也就感觉不出来了。

 

鼠标捕获概念:鼠标移到图形上并不是捕获,捕获是指鼠标在图形上被按下后(一定在按下后,也就是说按下鼠标的事件

通知仍是捕标进入时捕获到的mouseTarget图形),其意即为用鼠标捕获了该图形,此概念用于选择图形。

mouseTarget鼠标目标概念:没被捕获并且光标落其上

cursorTarget光标目标:光标在落在其上的图形。

 

图形的MinimumSize,MaximumSize,PreferredSize,Size,bounds区别:

    基本上来说,validate是对于尺寸的调整,而repaint()是对颜色的调整。当我们把一个图形C作为子图形拖到

    另一个图形P里的时候(想象PUML类图里表示类的矩形,C为表示属性或方法的矩形),因为调用了Padd()方法,

    所以PP的所有祖先图形都将通过revalidate()被置为invalid状态。UpdateManager随后在performUpdate()

    里对这些图形进行validate(),在validate()的过程中,每个图形将通过自己的LayoutManager重新计算自己的尺寸。

    这样就实现了P随子图形的多少自动改变大小。由上总结,布局为了控件的包容,自动让控件挪位(排挤),改变大小(

    如父控件装不下),以使界面外观作出调整,这些要用到PreferredSize及其它属性。

    MinimumSize指一个图形元素最小不能比它小

    MaximumSize指图形元素最大不能比它大

    PreferredSize的值一定介于MinimumSizeMaximumSize之间,如果小于MinimumSize就用MinimumSize,如果大于MaximumSize就用MaximumSizePreferredSize可以被布局调整

    sizebounds的宽度和高度

    bounds指图形元素的具体位置,包括左上角定点坐标、宽度和高度

    layout计算的就是PreferredSize

   

******更新管理器,图形的repaint,invalidate,validate,revalidate,布局之间关系:*********

LayoutManager(布局管理器)

 

布局管理器通过Figure#setBounds()改变子图形的位置和大小。

根据布局算法和子图形决定当前图形的preferredSize

布局的过程是先确定图形的大小,再计算每个子图形的新位置和大小。

Figure#invalidate()

 

valid属性已经是false则直接返回。

如果图形拥有LayoutManager,则调用LayoutManagerinvalidate()方法,在XYLayout里作用是将preferredSize重置为null值,在FlowLayout里还要把minimumSize置为null值。

将图形的valid属性置为false

Figure#revalidate()

 

我觉得它实际代表"recursive invalidate"的意思。这个方法的功能是首先将图形自己invalidate(),然后递归的将图形的父图形invalidate(),一直到根图形为止,这个根图形会被加入到UpdateManager的一个列表中。

Figure的很多方法里,如setBorder()setContstraint()setLayoutManager()add()remove()等,会自动调用revalidate()方法。因此,大部分情况下我们不需要手动调用这个方法。

Figure#validate()

 

valid属性已经是true则直接返回。

将图形的valid属性置为true

如果图形拥有LayoutManager,则调用LayoutManagerlayout()方法。

对图形的每个子图形,调用validate()方法。

Figure#repaint()

 

在图形的UpdateManager里,将图形所处的区域标记为区域,这个区域将由UpdateManager(定期)重画。

在图形的setVisible()setOpaque()setForegroundColor()setBounds()setBackgroundColor()等方法里会自动调用repaint()方法。

Figure#paint()

 

虽然名称相似,但这个方法和repaint()关系不大。在Figure里这个方法按顺序调用paintFigure()paintClientArea()paintBorder()这三个方法,当实现自己的Figure时,绝大多数情况下应该只覆盖paintFigure()而不是paint()本身。

Figure#getPreferredSize()

 

对于Label这样的图形,它的preferredSize由它所显示的文本和图标所占空间决定;如果一个图形包含子图形,则它的preferredSize要考虑子图形的排列方式,所以要由LayoutManager来决定。

LayoutManagergetPreferredSize()方法还有两个参数:wHinthHint,它们分别代表图形的已知长(宽)度,如果其中一个值是大于零的,则在另一个方向上子图形将换行(列)排列,以保证长(宽)度不大于这个已知值。

 

 

Figure#invalidate()

1、若valid属性已经是false则直接返回。

2、如果图形拥有LayoutManager,则调用LayoutManagerinvalidate()方法,在XYLayout里作用是将preferredSize重置为null值,在FlowLayout里还要把minimumSize置为null值。

3、将图形的valid属性置为false

 

IFigure#revalidate()

1、向上递归使包括本图形上源图形无效即调用invalidate()方法

2、递归寻到图形根并调用将根图形updateManager#addInvalidFigure(this)增加到无效图形列表,而该调用将用背后线程执行performUpdate从而执行有效化图形。

3、在Figure的很多方法里,如setBorder()setContstraint()setLayoutManager()add()remove()等,会自动调用revalidate()方法。因此,大部分情况下我们不需要手动调用这个方法。

 

Figure#validate()

1、若valid属性已经是true则直接返回。

2、将图形的valid属性置为true

3、如果图形拥有LayoutManager,则调用LayoutManagerlayout()方法。

4、对图形的每个子图形,调用validate()方法。

 

Figure#repaint()

1、在图形的UpdateManager里,将图形所处的区域标记为区域,这个区域将由

2UpdateManager(定期)重画。

3、在图形的setVisible()setOpaque()setForegroundColor()setBounds()4setBackgroundColor()等方法里会自动调用repaint()方法。

 

Figure#paint()

1、虽然名称相似,但这个方法和repaint()关系不大。在Figure里这个方法按顺序调用

2paintFigure()paintClientArea()paintBorder()这三个方法,当实现自己的

3Figure时,绝大多数情况下应该只覆盖paintFigure()而不是paint()本身。

 

Figure#getPreferredSize()

1、对于Label这样的图形,它的preferredSize由它所显示的文本和图标所占空间决定;

2、如果一个图形包含子图形,则它的preferredSize要考虑子图形的排列方式,所以要由LayoutManager来决定。

3LayoutManagergetPreferredSize()方法还有两个参数:wHinthHint,它们分别代表图形的已知长(宽)度,如果其中一个值是大于零的,则在另一个方向上子图形将换行(列)排列,以保证长(宽)度不大于这个已知值。

4、如果图形的perfsize为空则返回图形size,如果有布局则返回布局计算的perfsize

基本上来说,validate是对于尺寸的调整,而repaint()是对颜色的调整。当我们把一个图形C作为子图形拖到另一个图形P里的时候(想象PUML类图里表示类的矩形,C为表示属性或方法的矩形),因为调用了Padd()方法,所以PP的所有祖先图形都将通过revalidate()被置为invalid状态。UpdateManager随后在performUpdate()里对这些图形进行validate(),在validate()的过程中,每个图形将通过自己的LayoutManager重新计算自己的尺寸。这样就实现了P随子图形的多少自动改变大小。

上面左图是在子图形上发生改变时,自动调用了Fig4invalidate()方法,导致到根图形之间的所有图形的invalidate()方法被触发。右图则是UpdateManager对这些invalid图形进行validate(),并且是自上而下进行的(几乎可以认为validate()方法就是对layout()方法的调用)。注意到由于对Fig2进行了layout()Fig5的尺寸也可能因此发生改变,如果发生了这种情况,则Fig5invalidate()方法也会被调用

 

http://www.cnblogs.com/bjzhanghao/archive/ 2005/09/17 /237923.html

 

Figure#getPreferredSize()

LayoutManager#getPreferredSize(IFigure, int, int)

 

      

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值