技术开发 频道

SWT 全接触



3. 用SWT绘制2D图形

用SWT绘图通常由两种方法,一种是借助Graphics Context,另一种是利用Draw2D。然而Draw2D是一个基于SWT Composite的轻量级组件,于是在效率上,它无法体现出SWT的Native Code的速度优势。故其虽然强大,但仅适用于绘图工作不是系统瓶颈的应用程序。所以我在这里只介绍第一种方法。

3.1 Graphics Context

我们可以在任何实现了org.eclipse.swt.graphics.Drawable接口的类上绘制图形,这包括一个控件,一幅图像,一个显示设备或一个打印设备。类org.eclipse.swt.graphics.GC是一个封装了所有可执行的绘图操作的图形上下文(Graphics Context)。两种使用GC的方式我们已经在本节前言中提过,稍后会作详细说明。

3.2 在一幅图像上绘制图形

下面一段代码创建了一个带有图像的GC并在上面绘制了两条线:

Image image = new Image(display,"C:/music.gif"); GC gc = new GC(image); Rectangle bounds = image.getBounds(); gc.drawLine(0,0,bounds.width,bounds.height); gc.drawLine(0,bounds.height,bounds.width,0); gc.dispose(); image.dispose();


    一旦你创建了一个GC,你就有责任通过它的dispose方法释放它的资源。一个由应用程序创建的GC需要立即被绘制,然后尽快释放掉。这是因为每个GC都需要一个底层的系统资源,而在某些操作系统中这些资源是稀缺的,像Win98就只允许同时创建五个GC对象。

3.3 在Control上绘图

    类org.eclipse.swt.widgets.Control是可绘制的,所以你可以用像在图像上一样的方式来绘制图形。而和在图像上绘制所不同的是,如果你使用GC在一个Control上绘制图形,你需要知道当操作系统自身要绘制这个control的时候,它将覆盖掉你的改动。所以在一个Control上绘制图形的正确方法是加入其绘制事件的监听器。监听器类为org.eclipse.swt.events.PaintListener,其回调函数的参数是一个org.eclipse.swt.events.PaintEvent类的实例。这个PaintEvent实例中包含一个GC的引用,你可以向这个GC发送消息。下面的代码示例说明了如何建立这种类型的绘图:

Shell shell = new Shell(display); shell.addPaintListener(new PaintListener(){ public void paintControl(PaintEvent e){ Rectangle clientArea = shell.getClientArea(); e.gc.drawLine(0,0,clientArea.width,clientArea.height); } }); shell.setSize(150,150)


.4 剪切(Clipping)

GC的剪切域是可见绘图发生的部分。在缺省情况下,一个GC是一个被构造的可视部分边界。改变一个GC的剪切域可以让我们构造出各种图形效果。其中的一个例子是如果你想填充一个缺失了边缘的矩形。一种方法是绘制多边形矩形来组成所需要的图形,另一种方法就是剪切GC,然后对其剪切部分进行填充。


shell.addPaintListener(new PaintListener() {
            public void paintControl(PaintEvent e) {
            Rectangle clientArea = shell.getClientArea();
            int width = clientArea.width;
            int height = clientArea.height;
            e.gc.setClipping(20,20,width - 40, height - 40);
            e.gc.setBackground(display.getSystemColor(SWT.COLOR_CYAN));
            e.gc.fillPolygon(new int[] {0,0,width,0,width/2,height});
            }
            });
            

这段代码在Shell上的显示的过程效果如下:


3.5 画板(Canvas)

虽然任何Control都可以通过自身的paintEvent来绘制图形,但其子类org.eclipse.swt.widgets.Canvas是专门被设计用来进行图形操作的特殊的绘图类。我们既可以使用一个Canvas,再加入一个绘图监听器来实现绘图,也可以通过继承来建立一个可重用的自定义Control。Canvas有很多style bit,可以在绘图发生时产生作用。

3.6 绘制直线和图形

我们有很多方法可以在一个GC上画线,包括在两点之间,一系列离散的点之间或一个预定义的图形上都可以。直线是以GC的前景色来绘制的,我们可以通过GC绘制拥有不同厚度的各式直线。对于一个Paint事件,GC有着与Control组件一样的属性,即激发事件且缺省的直线样式固定为1个像素宽。

GC.drawLine(int x1, int y1, int x2, int y2);这条语句在可绘制的面板上的两点间花了一条直线,起始点为(x1,y1),终止点为(x2,y2)。终止点包含在画好的直线中。如果起始点等于终止点的话,将会有一个独立的象素点被绘制出来。

GC.drawPolyline(int[] pointArray);这条语句绘制了一系列互相连接的线段,作为参数的数组用于描述点的位置。语句gc.drawPolyline(new int[] { 25,5,45,45,5,45 });绘制了如下的图形:



GC.drawPolygon(int[] pointArray);与drawPolyline(int[])是类似的,唯一区别在于最后一个点和低一个点是连接的。gc.drawPolygon(new int[] { 25,5,45,45,5,45 });将会获得与上图一样的结果。

GC.drawRectangle(int x, int y, int width, int height);这条语句从左上角的(X,Y)点,用参数中的宽和高画出了一个矩形。gc.drawRectangle(5,5,90,45);将会绘制出如下图形:

    GC.drawRoundedRectangle(int x,int y,int width,int height,int arcWidth,int arcHeight);一个圆矩形与标准矩形的区别就在于其四个角是圆的。圆矩形的每一个角都可以被想象成为1/4个椭圆,并且arcWidth和arcHeight由完整的椭圆的宽和高决定。gc.drawRoundedRectangle(5,5,90,45,25,15);绘制了一个左上角位置为5.5的圆矩形,右边的图形是放大后的效果:



    GC.drawOval(int x, int y, int width, int height);一个椭圆是由其相对应的矩形的左上角的位置(x,y)来确定绘制位置的,其宽和高即为对应矩形的宽和高。对于圆形来说,只需要另宽和高相等即可。


GC.drawArc(int x, int y, int width, int height, int startAngle, int endAngle);曲线的绘制也是与一个相应的矩形有关,即其左上角的位置与宽和高都是相应矩形的属性。StartAntle是从横向的X开始计算的,所以0度指向的是东而不是北。曲线的绘制是从StartAngle到endAngle以逆时针方向执行。gc.drawArc(5,5,90,45,90,200);所绘制的图形如下:



3.7 绘制文本

文本可以被绘制在一个GC上, 字形是用GC的前景色和字体来绘制的,并且它所占用的区域是用GC背景色绘制的。要绘制文本,你需要定义要绘制文本的左上角,宽度和高度。有两组方法可以用来绘制文本,第一组方法的名字里都带有一个Text,并将会处理直线定界符和制表符。第二组API方法集的名字里都带有String,它们没有制表符或回车的处理,并主要用于控制像Eclipse的Java编辑器StyledText这样复杂的Control。


GC.drawText(String text, int x, int y);
            Font font = new Font(display,"Arial",14,SWT.BOLD | SWT.ITALIC);
            // ...
            gc.drawText("Hello World",5,5);
            gc.setForeground(display.getSystemColor(SWT.COLOR_BLUE));
            gc.setFont(font);
            gc.drawText("Hello\tThere\nWide\tWorld",5,25);
            // ...
            font.dispose();
            



drawText API将控制字符\t处理为制表符,将\n处理为回车符。


GC.drawString(String text, int x, int y);
            Font font = new Font(display,"Arial",14,SWT.BOLD | SWT.ITALIC);
            // ...
            gc.drawString("Hello World",5,5);
            gc.setForeground(display.getSystemColor(SWT.COLOR_BLUE));
            gc.setFont(font);
            gc.drawString("Hello\tThere\nWide\tWorld",5,25);
            // ...
            font.dispose()
            



当使用drawString时,制表符和回车符将不会被处理。

在一个GC上绘制字符的时候,一个字符串所占用的大小取决于它的内容以及GC的字体。想要确定一个字符串在被绘制之后所占用的区域可以使用方法:GC.stringExtent(String text), 或 GC.textExtent(String text)。这两个方法都返回一个Point类,这个Point的X和Y是渲染参数字符串所需要的宽和高。

0
相关文章