在使用 setXORMode 之前,应该使用 setBackground/setForeground 等方法来设定背景色或者前景色。另外,我们不可以把 setAntialias 或者 setTransform 等 跟该方法一起使用,否则你会惊讶地发现使用 setXORMode 并没有达到你想要得效果。为什么呢?这是因为使用 setAntialias 或者 setTransform 等方法之后,高级图像模式被自动的调用,你可以使用 setAdvance(false) 将模式切换至普通模式之后再调用 setXORMode 方法。例如清单 5 。
清单 5. XOR 失效示例gc.setBackground (display.getSystemColor (SWT.COLOR_BLUE)); gc.fillRectangle (0, 0, 60, 60); gc.setAntialias (SWT.OFF);// 调用了 setAntialias gc.setXORMode (true); gc.setBackground (display.getSystemColor (SWT.COLOR_YELLOW)); gc.fillRectangle (20, 20, 80, 80); gc.dispose ();
值得注意的是, 在部分平台上并不支持 setXORMode,因此在开发具有可移植性的程序时, 要谨慎使用setXORMode。
渐进色渐进色在绘图过程中有着广泛的应用,能够使得图形或者界面具有很好的视觉效果。它主要分为上下梯度渐进色和左右梯度渐进色两种。 GC 就提供了方法 fillGradientRectangle 来实现这一功能,当其第 5 个参数 boolean vertical 为 true 时,将绘制上下渐进色;否则绘制左右渐进色。清单 6 举例说明如何使用 fillGradientRectangle, 图 2 显示了绘制的效果。
默认情况下,只能用此方法绘充有渐进色的矩形,如果要绘制其他图形,可以结合 GC 的其他方法一起来绘制。
清单 6. 渐进色示例gc.setBackground(display.getSystemColor(SWT.COLOR_BLUE)); gc.setForeground(display.getSystemColor(SWT.COLOR_WHITE)); gc.fillGradientRectangle(0,0, 100, 100, true);
图 2. 渐进色效果图绘制透明文本方法 setAlpha 是用来设置透明度,参数为透明度值。见清单 7,效果图如图 3 所示。
清单 7. 绘制透明文本final Display display = new Display(); final Shell shell = new Shell(display); shell.setText(" 透明文本示例 "); final Font font = new Font(display, "Arial", 30, SWT.BOLD | SWT.ITALIC); final Image image = new Image(display, 450, 300); final Rectangle rect = image.getBounds(); GC gc = new GC(image); gc.dispose(); 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); // 图像拷贝 gc.setAlpha(100); // 设置透明度 Path path = new Path(display); gc.setBackground(display.getSystemColor(SWT.COLOR_GREEN)); gc.setForeground(display.getSystemColor(SWT.COLOR_BLUE)); path.addString(" 透明字体 ", 0, 0, font); gc.fillPath(path); gc.drawPath(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(); font.dispose(); display.dispose();
图 3. 透明文本效果图图像拷贝我们可以通过对图像的 ImageData 进行复制来完成图像的拷贝,除此之外, GC 提供了图像拷贝的 API 。方法 public void drawImage(Image image, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight) 允许用户拷贝源图像的任何一个方块。例如在清单 7 中,gc.drawImage(image, 0, 0, 100, 100, 0, 0, 100, 100) 是拷贝 image 左上角 100 × 100 方块。
文本大小与高级模式GC 提供了方法 textExtent(String string) 来获取文本的宽度和长度。这个方法看似简单,但实际上我们应该注意同一个文本在不同的绘图模式下(具体见高级绘图模式部分)得到的文本范围并不尽相同。例如清单 8,普通模式下,笔者在 Windows XP 下实验得到的 size 是(22,13),而在高级绘图模式下得到的 size 是(23,13)。因此,在使用方法 textExtent 来计算文本大小的时候应该考虑到绘图模式的不同可能会导致得到不同的结果。
清单 8. 计算文本大小GC gc = new GC (label); gc.setAdvanced(false/true); Point size = gc.textExtent ("hello"); gc.dispose ();
双缓冲区在使用 SWT 进行绘图时,我们经常会用到画布 (org.eclipse.swt.Canvas) 。开发者既可以通过类 Canvas 来进行绘图,也可以通过它来自定义一个特制的 Control 。画布默认的行为是在其更新自己之前,首先填充整个绘图区域的背景色,而这可能导致用户在原背景和将要填充的背景之间看到闪烁。其中一种解决方法是让画布的样式设成 SWT.NO_BACKGROUND, 但是此时我们需要负责整个图形的绘制。
另外一种情况时,当我们变化其大小时,这也会触发重画事件。特定情况下可以设定 SWT.NO_REDRAW_RESIZE 样式来减少闪烁(例如仅仅缩小),但是并不是每一种情况下都适用。例如清单 9 所示。
清单 9. 用 SWT.NO_REDRAW_RESIZE 消除闪屏shell.setLayout(new FillLayout()); final Canvas canvas = new Canvas(shell,SWT.NO_REDRAW_RESIZE); canvas.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { Rectangle clientArea = canvas.getClientArea(); e.gc.setBackground(new Color(null, 255, 0, 0)); e.gc.fillArc(0, 0, clientArea.width,clientArea.height, 30, 30); } });
当你用鼠标拖着窗口的右下角进行缩放时,你会发现出现各种奇怪的现象。这是因为放大时如果使用 SWT.NO_REDRAW_RESIZE 样式将会导致部分区域更新不正常。