Draw2d里的Invalidating和Updating

本文部分内容来自Building a Database Schema Diagram Editor with GEF和GEF and Draw2d Plug-in Developer Guide,是对Draw2D里一些基本概念的说明。

LayoutManager(布局管理器)

  • 布局管理器通过Figure#setBounds()改变子图形的位置和大小。
  • 根据布局算法和子图形决定当前图形的preferredSize。
  • 布局的过程是先确定图形的大小,再计算每个子图形的新位置和大小。 

Figure#invalidate()

  • 若valid属性已经是false则直接返回。
  • 如果图形拥有LayoutManager,则调用LayoutManager的invalidate()方法,在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,则调用LayoutManager的layout()方法。
  • 对图形的每个子图形,调用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来决定。
  • LayoutManager的getPreferredSize()方法还有两个参数:wHint和hHint,它们分别代表图形的已知长(宽)度,如果其中一个值是大于零的,则在另一个方向上子图形将换行(列)排列,以保证长(宽)度不大于这个已知值。

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

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

posted @ 2005-09-15 21:11  八进制  阅读(3515)  评论(8编辑  收藏  举报