Canvas 是最基本的控件类型之一,可以用它来创建定制控件或绘图。图 2 和 图 3 展示了使用 Canvas 来绘制由重叠的矩形和椭圆形组成的图片的一个例子。在这幅绘画中,一些图片被填充,而其他一些则没有被填充。颜色、大小和位置的分配是随意的。
清单 2 展示了用于创建 Canvas 的代码。要实际地在 Canvas 上进行绘图,必须向该 Canvas 添加一个 PaintListener。每当 Canvas 需要重新绘制其客户机区域的任何部分时,都需要调用其 paintControl 方法。有两种绘制风格:
直接绘制 —— 很简单,但内容在整个重绘期间是不稳定的。
在进行绘制之前构建一个模型,然后再根据此模型进行重新绘制 —— 比较复杂,但很稳定。这通常是首选方法。
清单 2. 用于创建 Canvas 的方法
2 PaintListener pl) {
3 Canvas c = new Canvas(parent, style);
4 if (pl != null) {
5 c.addPaintListener(pl);
6 }
7 return c;
8 }
9 protected Canvas createCanvas(Composite parent, PaintListener pl) {
10 return createCanvas(parent, SWT.NONE, pl);
11 }
12
作为绘制风格 2 的一个例子,可以考虑一下清单 3 中定义的简单模型:
清单 3. PaintItems 的层次结构
2 public Color color;
3 public void paint(GC gc) {
4 gc.setForeground(color);
5 gc.setBackground(color);
6 }
7 }
8 abstract protected class BaseRectItem extends PaintItem {
9 public boolean fill;
10 public Rectangle extent;
11 }
12 protected class ElipseItem extends BaseRectItem {
13 public void paint(GC gc) {
14 super.paint(gc);
15 if (fill) {
16 gc.fillOval(extent.x, extent.y,
17 extent.width, extent.height);
18 }
19 else {
20 gc.drawOval(extent.x, extent.y,
21 extent.width, extent.height);
22 }
23 }
24 }
25 protected class RectangleItem extends BaseRectItem {
26 public void paint(GC gc) {
27 super.paint(gc);
28 if (fill) {
29 gc.fillRectangle(extent.x, extent.y,
30 extent.width, extent.height);
31 }
32 else {
33 gc.drawRectangle(extent.x, extent.y,
34 extent.width, extent.height);
35 }
36 }
37 }
38
这些绘制项都由 清单 4 中显示的 PaintListener 绘制。paintControl 方法是随在其上进行绘制的图形上下文(org.eclipse.swt.graphics 包中的 GC)一起提供的。您可以使用 GC 绘制文本和许多形状。此代码将重用通过 Display 类可用的标准系统颜色。由 Canvas 决定是否使用某种背景色填充其区域。gcObjects 集合包含所有需要绘制的 PaintItem 实例。数组 colorIds 是一个到选定的系统颜色的映射。
清单 4. 用于创建 TabFolder 和 TabItem 的方法
2 public void paintControl(PaintEvent e) {
3 GC gc = e.gc;
4 gc.setBackground(canvas.getDisplay().
5 getSystemColor(colorIds[0]));
6 Point cext = canvas.getSize();
7 gc.fillRectangle(0, 0, cext.x, cext.y);
8 for (Iterator i = gcObjects.iterator();
9 i.hasNext();) {
10 PaintItem pi = (PaintItem)i.next();
11 pi.paint(gc);
12 }
13 }
14 }…
15 protected static int[] colorIds = {
16 SWT.COLOR_WHITE, SWT.COLOR_BLUE, SWT.COLOR_CYAN,
17 SWT.COLOR_GRAY, SWT.COLOR_GREEN, SWT.COLOR_MAGENTA,
18 SWT.COLOR_RED, SWT.COLOR_YELLOW, SWT.COLOR_BLACK
19 };
20
清单 5 中显示了一些代码,这些代码先清除绘画,然后创建由一组矩形和椭圆组成的绘画。通过 GUI 上的按钮可以激活此代码。
清单 5. 用于处理绘制事件的方法
2 gcObjects.clear();
3 canvas.redraw();
4 }
5 public void doDraw() {
6 gcObjects.clear();
7 Display display = drawButton.getDisplay();
8 // create a bunch of objects
9 for (int i = 0; i < 50; i++) {
10 if (i % 2 == 0) {
11 RectangleItem ri = new RectangleItem();
12 ri.extent = new Rectangle(nextInt(500), nextInt(250),
13 nextInt(500), nextInt(250));
14 ri.color = display.
15 getSystemColor(colorIds[nextInt(colorIds.length)]);
16 ri.fill = i % 3 == 0;
17 gcObjects.add(ri);
18 }
19 else {
20 ElipseItem ei = new ElipseItem();
21 ei.extent = new Rectangle(nextInt(500), nextInt(250),
22 nextInt(500), nextInt(250));
23 ei.color = display.
24 getSystemColor(colorIds[nextInt(colorIds.length)]);
25 ei.fill = i % 5 == 0;
26 gcObjects.add(ei);
27 }
28 }
29 canvas.redraw();
30 }
31