SWT 绘图技术
Standard Widget Toolkit ( SWT,标准窗口小部件工具箱 ),是在 Eclipse 平台上使用的窗口小部件工具箱,它能向开发者提供和本机平台一致的用户界面和比较稳定的性能,并封装了大量的绘图 API,提供了强大的图像处理和绘图功能。在文章 SWT 图像处理入门中已经详细介绍了如何用 SWT 封装的 Image,ImageData 等类实现常用的图像处理功能,本文将重点介绍 SWT 高级绘图模式(其中包含 GDI+ 的高级特性:变换、路径、透明度、反锯齿)、图形上下文(其中包含 XOR 方法与高级模式、绘制渐进色、图像拷贝、计算文本大小与高级模式),最后将介绍如何使用双缓冲区来消除闪屏。
简介相信对 SWT 有一定了解的人都知道,SWT 为我们开发人员提供了大量与绘图相关的 API,大大降低了我们工作学习当中使用 Java 技术进行开发的难度。为了正确的使用 SWT 所提供的一系列绘图接口,读者有必要对 SWT 高级模式、图形上下文、双缓冲区等绘图相关的问题有一个大概地了解。表 1 列举了文章中出现的所有代码清单以及其所对应的名称。
表 1. 示例代码清单代码清单名称
清单 1保持输出一致性示例
清单 2图形旋转(用变换矩阵)
清单 3图形旋转(调用旋转函数)
清单 4二次方曲线路径
清单 5XOR 失效示例
清单 6渐进色示例
清单 7绘制透明文本
清单 8文本大小与高级模式
清单 9用 SWT.NO_REDRAW_RESIZE 消除闪屏
清单 10实现 DOUBLE BUFFERED
清单 11设置 SWT.DOUBLE_BUFFERED 样式
高级绘图模式在 Eclipse 3.1 Release 中, SWT 高级绘图模式作为平台新特性被添加进来。在高级绘图模式下,开发人员可以使用普通绘图模式下没有的 GDI+ 高级特性,例如变换、路径、透明度、反锯齿等。下面将逐个介绍如何使用这些 GDI+ 高级特性。
模式开关方法 setAdvance 是系统高级图形子系统的开关,当参数为 true 时,GC 将采用系统高级图形子系统来进行绘图(注意:某些操作系统只有一个绘图子系统,从普通模式切换到高级绘图模式将不起任何作用)。值得注意的是,高级图形子系统将被自动的调用,如果方法 setAlpha(int alpha)、setAntialias(int antialias) 等被调用的话。由于高级模式和普通模式的不同,其输出也可能不同。因此,如果要使用高级模式,应该在所有的绘图操作之前,切换当前模式为高级模式以保证输出的一致性。例如清单 1 。
清单 1:保持输出一致性示例boolean isAdvanced = gc.getAdvanced(); gc.setAdvanced(true/false); // 进行各种操作 … … // 恢复绘图模式 gc.setAdvanced(isAdvanced);
变换除了在文章 SWT 图像处理入门中提到的利用 ImageData 完成各种图形变换之外,SWT 高级模式下的类 Transform 为用户提供了另外一种选择。类 org.eclipse.swt.graphics.Transform 封装了图像的反向 (void invert())、旋转 (void rotate(float angle),参数 angle 为旋转角度 )、拉伸 (void scale(float scaleX, float scaleY)) 等操作,另外它还提供获取和设置变换矩阵的方法。清单 2 和 3 分别演示了两种利用 Transform 来完成图形的旋转 45 度。
清单 2. 图形旋转(用变换矩阵)GC gc = e.gc; gc.setAdvanced(true); if (!gc.getAdvanced()) { gc.drawText("Advanced graphics not supported", 30, 30, true); gc.dispose(); return; } gc.drawImage(image, x, y); Transform transform = new Transform(display); float cos45 = (float)Math.cos(Math.PI/4); float sin45 = (float)Math.sin(Math.PI/4); transform.setElements(cos45, sin45, -sin45, cos45, 0, 0); gc.setTransform(transform); gc.drawImage(image, 350, 100); transform.dispose(); gc.dispose();
清单 3. 图形旋转(调用旋转函数)GC gc = e.gc; gc.setAdvanced(true); if (!gc.getAdvanced()) { gc.drawText("Advanced graphics not supported", 30, 30, true); gc.dispose(); return; } gc.drawImage(image, x, y); Transform transform = new Transform(display); transform.rotate(45); gc.setTransform(transform); gc.drawImage(image, 350, 100); transform.dispose(); gc.dispose();
路径路径指得是二维系统中的路径。它不一定是连续的,可以是直线、矩形、弧形、立方体、文字,甚至是二次方曲线等其他路径。清单 4 演示了二次方曲线路径,如图 1 所示。
清单 4. 二次方曲线路径final Display display = new Display(); final Shell shell = new Shell(display); shell.setText("二次方曲线路径"); final Image image = new Image(display, 400, 300); final Rectangle rect = image.getBounds(); shell.addListener(SWT.Paint, new Listener() { public void handleEvent(Event event) { GC gc = event.gc; gc.drawImage(image,0,0, rect.width, rect.height,0,0, rect.width / 2, rect.height / 2); Path path = new Path(display);// 绘制二次方曲线路径path.quadTo(2,60,60,140); gc.setBackground(display.getSystemColor(SWT.COLOR_GREEN)); gc.setForeground(display.getSystemColor(SWT.COLOR_BLUE)); gc.fillPath(path); gc.drawPath(path);// 记住释放 Path 资源path.dispose(); } }); shell.setSize(shell.computeSize(rect.width / 2, rect.height / 2)); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); } image.dispose(); display.dispose();
图 1. 路径示意图透明度与反锯齿透明度、反锯齿这两个特性在绘图中也有着广泛的应用。我们在实际开发中经常会用到透明文本等来增加视觉效果,在图形上下文章节中将演示如何绘制透明文本。
在绘图或者图像处理中,缩放等操作会导致明显的锯齿和失真。 SWT 高级绘图模式允许用户使用 GC.setAntialias(int antialias) 来使能 / 禁止反锯齿功能。
图形上下文 (Graphics Context)谈到 SWT 的绘图技术,我不得不谈到 GC (Graphics Context) 。 org.eclipse.swt.graphics.GC 封装了大量的绘图 API,其中包含常见的绘图技术,例如如何绘制不同厚度和不同样式的直线、如何绘制文本和各式各样的字体、图像以及如何填充图形。如果读者不是很熟悉这部分的内容,可以阅读参考文献中列举的相关资料自行学习。下面我将介绍一些重要的方法。
异或 (XOR) 与高级模式方法 setXORMode(true) 的作用是使得目标颜色是源和目标颜色进行异或操作 (XOR) 所得到的结果值。当参数为 false 时,则取消了绘图的异或效果。