让 Eclipse 插件程序具有二维作图能力(3)

发表于:2007-07-14来源:作者:点击数: 标签:
· 渲染器是如何工作的 SWT/Draw2D Java 2D 渲染器的工作过程如下: 在可以使用渲染器之前,必须以至少与要绘制的区域一样的尺寸初始化其屏外图像和缓冲区。这是通过调用方法 prepareRendering(...) 完成的。根据是在 SWT 还是 Draw2D 图形上下文中进行渲染
· 渲染器是如何工作的

SWT/Draw2D Java 2D 渲染器的工作过程如下:

在可以使用渲染器之前,必须以至少与要绘制的区域一样的尺寸初始化其屏外图像和缓冲区。这是通过调用方法 prepareRendering(...) 完成的。根据是在 SWT 还是 Draw2D 图形上下文中进行渲染,这个方法以一个 SWT GC 或者一个 Draw2D Graphics 对象作为参数。

接下来,prepareRendering 从图形上下文中提取剪裁矩形(clip rectangle)—— 剪裁矩形,是可以修改其中像素的最大矩形区域。然后调用 private 方法 prepareRendering(int clipX, int clipY, int clipW, int clipH) 准备要渲染的屏外图像。这个方法独立于所使用的图形上下文的类型,它可以是 SWT 或者 Draw2D。prepareRendering() 方法的工作过程如下:

它首先检查 AWT 和 SWT 屏外图像已实例化并足以包含要绘制的区域,这是由方法 checkOffScreenImages(clipW, clipH) 完成的。如果屏外图像已经实例化,但是不够大,就会放弃它并以所需要大小重新创建一个。如果屏外图像大于要绘制的区域,那么就会重复使用它,并只修改相应于要绘制的区域的那一部分。

完成这种检查后,用为透明度信道保留的颜色 TRANSPARENT_COLOR 填充绘制区域。这个图像就可以用来进行 Java 2D 操作了。当渲染器准备好进行剪裁区域中的 Java 2D 绘制操作后,可以从 BufferedImage AWT 获得 Java 2D Graphics2D 上下文。这个图形上下文将用于所有 Java 2D 绘制例程。每一次绘制操作修改 AWT 屏外图像。

当所有 Java 2D 绘制操作都完成后,绘制区域的像素必须从 AWT 转换为 SWT 屏外图像,然后绘制到 SWT 或者 Draw2D 图形上下文中。这个操作是由方法 render(GC) 或者 render(Graphics) 完成的。这两个方法都在内部调用 private 方法 transferPixels(...),该方法将像素从 AWT 转换为 SWT。

如果不再需要渲染器了或者必须释放资源,可以调用 dispose() 方法,以清除渲染器所使用的屏外图像和缓冲区。这会释放资源,但是在再次需要渲染器时要花时间重新创建缓冲区。需要根据组件重新绘制的频度以及重新绘制区域应有多大来判断应当什么时候调用 dispose()。

清单 2 显示如何用渲染器在 SWT Canvas 上绘制一些旋转文字。

清单 2. 在 SWT Canvas 上的使用示例

Canvas canvas = new Canvas(shell, SWT.NO_BACKGROUND);
final Graphics2DRenderer renderer = new Graphics2DRenderer();

canvas.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
Point controlSize = ((Control) e.getSource()).getSize();

GC gc = e.gc; // gets the SWT graphics context from the event

renderer.prepareRendering(gc); // prepares the Graphics2D renderer

// gets the Graphics2D context and switch on the antialiasing
Graphics2D g2d = renderer.getGraphics2D();
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

// paints the background with a color gradient
g2d.setPaint(new GradientPaint(0.0f, 0.0f, java.awt.Color.yellow,
(float) controlSize.x, (float) controlSize.y, java.awt.Color.white));
g2d.fillRect(0, 0, controlSize.x, controlSize.y);

// draws rotated text
g2d.setFont(new java.awt.Font("SansSerif", java.awt.Font.BOLD, 16));
g2d.setColor(java.awt.Color.blue);

g2d.translate(controlSize.x / 2, controlSize.y / 2);
int nbOfSlices = 18;
for (int i = 0; i < nbOfSlices; i++) {
g2d.drawString("Angle = " + (i * 360 / nbOfSlices) + "\u00B0", 30, 0);
g2d.rotate(-2 * Math.PI / nbOfSlices);
}

// now that we are done with Java 2D, renders Graphics2D operation
// on the SWT graphics context
renderer.render(gc);

// now we can continue with pure SWT paint operations
gc.drawOval(0, 0, controlSize.x, controlSize.y);
}
});



代码说明:

创建一次渲染器,并在每次需要重新绘制画布(canvas) 时重复使用它。

实例化画布,并在它上面添加一个 PaintListener 以执行绘制操作。

从 PaintEvent 获得图形上下文 gc。

渲染器是在图形上下文中准备的,这意味着屏外图像可以接受绘制操作。

在下一步,获得 Java 2D 图形上下文 g2d。

然后实现一组 Java 2D 绘制操作以用渐变颜色绘制背景并且每 20 度绘制一个旋转的文字。这个过程使用图形上下文的平移和几个旋转。

最后,调用 render(GC) 方法以将 Java 2D 绘制操作传输到 SWT 图形上下文。可以在同一绘制例程中使用 Java 2D 和纯 SWT 绘制操作。

渲染操作的结果

渲染操作的结果如图 4 所示。在这个例子中,没有丢弃渲染器,在每次绘制 Canvas 时可以重复使用它的屏外图像和内部缓冲区,这样可以节省实例化和垃圾收集的时间。记住,如果画布不需要经常重新绘制,并且渲染器所占用的资源非常重要,那么可以在每次绘制操作后丢弃渲染器。


图 4. 使用示例:用 Java 2D 例程帮助绘制 SWT

清单 3 显示如何在 Draw2D 图像中实现同样的例子。在这里是通过覆盖 Figure 的方法 paintClientArea(Graphics) 来实现绘制 Figure。Graphics2DRenderer 的使用与上一个例子完全一样。惟一的区别是,方法 prepareRendering 和 render 这一次是以一个 Draw2D Graphics 而不是一个 SWT GC 为参数调用的。

清单 3. 对 Draw2D 图的使用示例

final Graphics2DRenderer renderer = new Graphics2DRenderer();

IFigure figure = new Figure() {
protected void paintClientArea(org.eclipse.draw2d.Graphics graphics) {
Dimension controlSize = getSize();
renderer.prepareRendering(graphics); // prepares the Graphics2D renderer

// gets the Graphics2D context
Graphics2D g2d = renderer.getGraphics2D();

(...) // does the Java 2D painting

// now that we are done with Java 2D, renders Graphics2D operation
// on the Draw2D graphics context
renderer.render(graphics);

// now we can continue with pure Draw2D paint operations
graphics.drawOval(0, 0, controlSize.width, controlSize.width);
}
};


本文展示的技术,使得将 Java 2D 功能集成到 SWT 和 GEF 应用程序中成为可能并且相当容易。我一步一步地展示了如何结合 SWT 和 Java 2D 的最好功能并将结果绘制到任何 SWT 组件或者 GEF Draw2D 图像上。这里展示的技术就像代码示例这样简单:只用几行代码就可以实现,不需要依赖任何外部库,也不需要启动一个 AWT 线程。

原文转自:http://www.ltesting.net