尽管一个新的figure可以由多个自组合而成,但是归根结底figure还是画出来的,所以了解figure中GC画的顺序和步骤,对自己扩展一个新的figure是有帮助的。
1.paint:
public void paint(Graphics graphics) {
if (getLocalBackgroundColor() != null)
graphics.setBackgroundColor(getLocalBackgroundColor());
if (getLocalForegroundColor() != null)
graphics.setForegroundColor(getLocalForegroundColor());
if (font != null)
graphics.setFont(font);
graphics.pushState();
try {
paintFigure(graphics);
graphics.restoreState();
paintClientArea(graphics);
paintBorder(graphics);
} finally {
graphics.popState();
}
}
在figure类中有paint的默认实现,在paint中基本上有四个步骤:
1.设置背景,前景颜色,设置字体样式
2.paintFigure描绘figure自身特点,包括背景颜色之类
3.paintClientArea描绘的区域,规范点说,这里才是我们具体绘制图形的地方
4.paintBorder描绘border
从这个顺序可以看出,孩子是在自己的上面的,边框是在孩子和自己的上面的。
2.paintFigure:
protected void paintFigure(Graphics graphics) {
if (isOpaque())
graphics.fillRectangle(getBounds());
if (getBorder() instanceof AbstractBackground)
((AbstractBackground) getBorder()).paintBackground(this, graphics,
NO_INSETS);
}
在Figure类里面,对自己的描绘内容很简单,判断是否为透明,如果不是就填充颜色。另外,AbstractBackground我就
看到了一个实现类还是emf的,emf用于画阴影在这。其实上面有一个绘制Border的地方,为啥这个地方还来一个,不清
楚。
3.paintClientArea:
protected void paintClientArea(Graphics graphics) {
if (children.isEmpty())
return;
boolean optimizeClip = getBorder() == null || getBorder().isOpaque();
if (useLocalCoordinates()) {
graphics.translate(getBounds().x + getInsets().left, getBounds().y
+ getInsets().top);
if (!optimizeClip)
graphics.clipRect(getClientArea(PRIVATE_RECT));
graphics.pushState();
paintChildren(graphics);
graphics.popState();
graphics.restoreState();
} else {
if (optimizeClip)
paintChildren(graphics);
else {
graphics.clipRect(getClientArea(PRIVATE_RECT));
graphics.pushState();
paintChildren(graphics);
graphics.popState();
graphics.restoreState();
}
}
}
如果无子直接返回,说明这个方法里面确实是主要用于绘制子的内容的。
optimizeClip判断是否选用已经设置的区域进行绘制,如果你自己设置了Bounds的大小,这里是会获取到的。useLocalCoordinates是否选用相对坐标
graphics.translate:这个方法是用来确定相对坐标的起始位置,也就是相对的原点。
paintChildren:绘制子
4.paintChildren:
protected void paintChildren(Graphics graphics) {
for (int i = 0; i < children.size(); i++) {
IFigure child = (IFigure) children.get(i);
if (child.isVisible()) {
// determine clipping areas for child
Rectangle[] clipping = null;
if (clippingStrategy != null) {
clipping = clippingStrategy.getClip(child);
} else {
// default clipping behaviour is to clip at bounds
clipping = new Rectangle[] { child.getBounds() };
}
// child may now paint inside the clipping areas
for (int j = 0; j < clipping.length; j++) {
if (clipping[j].intersects(graphics
.getClip(Rectangle.SINGLETON))) {
graphics.clipRect(clipping[j]);
child.paint(graphics);
graphics.restoreState();
}
}
}
}
}
先判断子是否可见,可见才绘制。
clippingStrategy:这里的裁剪策略,把孩子裁剪成很多块(胡乱理解的),因为有超出的问题。这个东西没有仔细研究,抽时间研究研究。从循环中的逻辑来看,或许是子的内容太多分多次画。