SWT高级控件之SWT系统资源

来源:互联网 发布:伺服电机脉冲输出编程 编辑:程序博客网 时间:2024/04/29 20:45

系统资源包括颜色(Color)、字体(Font)、光标(Cursor)、图像(Image)等,对于这些本地系统资源,在使用后一定要释放掉,否则会严重影响系统的整体性能。

12.1 系统资源概述

    系统资源一般是指颜色(Color)、字体(Font)、光标(Cursor)、图像(Image)等,SWT中创建的各种控件也属于系统资源。当在SWT中创建了系统资源,那么也就创建了对应的本地资源。
下面这种方式创建的资源必须释放:
// 创建红色对象
Color color = new Color(diaplay, 255, 0, 0);
// 使用完时释放
color.dispose();
下面这种方式获取的资源不需释放:
// 获得系统中的红色对象
Color color = display.getSystemColor(SWT.COLOR_RED);
因为这种方式是从底层平台获得的颜色资源,这个资源不是我们自己创建的,只是被我们引用了,其他的对象有可能正在使用或者将要使用这个资源,释放这样的资源会带来不可预知的严重后果。

JAVA的垃圾回收只能回收Java虚拟机中的对象,而对本地操作系统的对象是不能够自动释放的,所以对本地资源的释放一定要显式的释放掉。

释放资源的原则
1. 通过new创建的资源一定要显式的释放。
2. 释放了父控件也就释放了子控件。例如窗口(Shell)对象中有一个按钮(Button),释放Shell时该Button也隐式的释放了。该规则只适用于Widget的子类。如果程序中使用了字体、颜色、图像、图标等系统资源,扔需要在程序中显示的dispose()掉。
3. 释放了控件也就释放了控件所设置的菜单。

访问资源的原则
SWT中不允许访问已经释放了的控件,否则会抛出异常“Widget is disposed”。可以使用控件对象的isDisposed()方法判断控件是否已经被释放了。

何时释放资源
1. 最简单的情况:使用完就释放。
2. 在释放控件事件widgetDisposed()的方法中释放资源。
   // 注册窗口释放时所触发的事件
   shell.addDisposeListener(new DisposeListener(){
    // 当窗口释放时
    public void widgetDisposed(DisposeEvent e) {
     if (!cursor.isDisposed()) {
      cursor.dispose();
     }
    }
   });

12.1 颜色(Color)

 

◆ 系统颜色
    系统颜色是SWT内置的一些常见的颜色。
Color color = display.getSystemColor(SWT.COLOR_BLUE);
此种方法使用的颜色不需要释放。

◆ RGB颜色
    颜色一般是由三原色也就是红(Red)、绿(Green)、蓝(Blue)3种颜色通过不同的组合形成的。
RGB black = new RGB(0, 0, 0); // 黑色
Color color = new Color(display, black);

或:
Color color = new Color(display, 0, 0, 0);
此种方法创建的颜色在使用完后需要释放掉。

Color类的常用方法:
获得蓝色的值:getBlue()
获得绿色的值:getGreen()
获得红色的值:getRed()
获得颜色的RGB对象:getRGB()

12.3 字体(Font)

    SWT中涉及字体的类有Font和FontData。FontData携带了一些字体的信息,包括字体名、字体大小等。

Font类的构造方法有以下3种:
◆ Font(Device device, String name, int height, int style)。例如:
Font font = new Font(display, "Courier", 10, SWT.NORMAL);
Courier为字体名称,10为字体的大小。SWT.NORMAL为字体样式,还可以为SWT.BOLD或SWT.ITALIC。
◆ Font(Device device, FontData fd)
FontData data = new FontData("Courier", 10, SWT.NORMAL);
Font font = new Font(display, data);

◆ Font(Device device, FontData[] fds)
FontData[] data = new FontData[2];
data[0] = new FontData("Courier", 10, SWT.NORMAL);
data[1] = new FontData("宋体", 10, SWT.NORMAL);
Font font = new Font(display, data);


获取系统默认字体:
Font font = display.getSystemFont();

举例:
   FontData data = new FontData();
   data.setHeight(18);
   data.setStyle(SWT.BOLD|SWT.ITALIC|SWT.WRAP);
   data.setName("Courier");
   final Font font = new Font(display, data);
  
   Text text = new Text(shell, SWT.MULTI|SWT.BORDER|SWT.WRAP|SWT.V_SCROLL);
   text.setFont(font);
   shell.layout();
...
font.dispose();

显示效果:

12.4 光标(Cursor)

 

1. 系统光标
Cursor cursor = new Cursor(display, SWT.CURSOR_HAND);
2. 自定义光标
Cursor(Device device, ImageData source, ImageData mask, int hotspotX, int hotspotY)
Cursor(Device device, ImageData source, int hotspotX, int hotspotY)
source为光标使用的光标文件,hotspotX、hotspotY为光标进入到有效区域内的X和Y坐标值,mask为光标滤镜效果。

举例如下:
   Display display = new Display();
   ImageData sourceData = new ImageData ("F://icons//cursor.jpg");
   final Cursor cursor = new Cursor(display , sourceData ,10, 10);
   Shell shell = new Shell(display);
   shell.setSize(150, 150);
   shell.setLayout(new FillLayout());
   shell.open();
   shell.setCursor(cursor);
   // 注册窗口释放时所触发的事件
   shell.addDisposeListener(new DisposeListener(){
    // 当窗口释放时
    public void widgetDisposed(DisposeEvent e) {
     if (!cursor.isDisposed()) {
      cursor.dispose();
     }
    }
   });
   while (!shell.isDisposed()) {
    if (!display.readAndDispatch())
     display.sleep();
   }
   display.dispose();

12.5 图像(Image)

 

1. 画布类(Canvas)
该类继承自Composite类。

package www.swt.com.ch12;

import org.eclipse.swt.events.*;

public class CanvasSample {
private Image image = null;
private Shell shell = null;
private Canvas canvas = null;
public CanvasSample() {
   createContent();
}
public void createContent() {
   shell = new Shell();
   shell.setLayout(new FillLayout());
   // 创建一个图像对象
   image = new Image(shell.getDisplay(), getClass().getResourceAsStream("eclipse48.gif"));
   // 创建一个画布对象
   canvas = new Canvas(shell, SWT.NONE);
   // 注册画布的画图事件
   canvas.addPaintListener(new PaintListener() {
    public void paintControl(PaintEvent e) {
    // 在画布上显示图像,图像在画布中的坐标是距左边10个像素,距上边10个像素
     e.gc.drawImage(image, 10, 10);
    }
   });
   shell.setSize(200, 150);
}
public Canvas getCanvas() {
   return canvas;
}
public void setCanvas(Canvas canvas) {
   this.canvas = canvas;
}
public Image getImage() {
   return image;
}
public void setImage(Image image) {
   this.image = image;
}
public Shell getShell() {
   return shell;
}
public void setShell(Shell shell) {
   this.shell = shell;
}
public static void main(String[] args) {
   Display display = Display.getDefault();
   CanvasSample cSample = new CanvasSample();
   cSample.getShell().open();
   while (!cSample.getShell().isDisposed()) {
    if (!display.readAndDispatch())
     display.sleep();
   }
   cSample.getImage().dispose();
   display.dispose();
}
}

显示效果:

◆ 创建画布时的样式还可以是:SWT.NO_REDRAW_RESIZE、SWT.NO_BACKGROUND、SWT.NO_MERGE_PAINTS等。
◆ 若要在画布上绘制图像,需在画布的画图事件PaintEvent中完成。

2. 图像类(Image)
创建图像的方法:
◆ Image (Device device, String filename)
Image image = new Image(display, "F://icon//cursor.gif");
◆ Image (Device device, InputStream stream):stream表示图片文件的数据流
Image image = new Image(display, getClass().getResourceAsStream("eclipse48.gif"));
◆ Image(Device device, Image srcImage, int flag)
这种方法可以简单的将图片转换成不同风格的图像对象。例如,将一张图片转换成灰色的图片代码如下:
Image image = new Image(display, getClass().getResourceAsStream("eclipse48.gif"));
Image grayImage = new Image(display, image, SWT.IMAGE_GRAY); // 灰色
Image grayImage = new Image(display, image, SWT.IMAGE_GRAY); // Disable
效果如下:


◆ Image(Device device, ImageData data)
ImageData data = new ImageData("F://icon//cursor.gif");
Image image = new Image(display, data);

3. 图像数据类(ImageData)
ImageData对象可以在转化成Image图像之前对图片进行包装加工,比如放大图片、设置图片透明度等。

创建ImageData类的常用方法:
◆ ImageData(InputStream stream):以图片文件的数据流作为参数。
◆ ImageData(String filename):以图片的路径作为参数。

ImageData类的属性和常用方法:
◆ height、width表示图片的高和宽,type表示图片的类型。支持的类型有SWT.IMAGE_BMP、SWT.IMAGE_BMP_RLE、SWT.IMAGE_GIF、SWT.IMAGE_ICO、SWT.IMAGE_JPEG、SWT.IMAGE_PNG。
◆ data:图像的二进制数组,类型为byte[]。
◆ getRGBs():获得该图像所包含的RGB颜色。
◆ scaledTo(int width, int height):放大图片的方法。返回一个新的ImageData对象,而不改变当前的图片大小。
举例如下:
     ImageData data = image.getImageData();
     Image i1 = new Image(e.display, data);
     e.gc.drawImage(i1, 10, 10);
    
     ImageData doubleImage = data.scaledTo(data.width*2, data.height*2);
     Image i2 = new Image(e.display, doubleImage);
     e.gc.drawImage(i2, 80, 10);
    
     i1.dispose();
     i2.dispose();

显示效果:

4. 保存图像类(ImageLoader)
    对于通过ImageData加工后的图像可以使用ImageLoader对象保存为新文件。
举例如下:
     ImageData doubleImage = data.scaledTo(data.width*2, data.height*2);
     ImageLoader loader = new ImageLoader();
     // 设置图像的数据
     loader.data = new ImageData[]{doubleImage};
     loader.save("F://icons//doubleImage.gif", SWT.IMAGE_GIF);

常用加载图片的方法:
◆ load(InputStream stream):指定输入流加载。
◆ load(String filename):指定文件路径加载。

注意:该类使用的都是ImageData[]数组,原因是如果图片格式为gif时,可能为一个动态的图片,一个动态的图片可能由多个图片构成,使用数组是为了保存动态图片的。
对于像gif的图片还可以设置repeatCount属性,表示多帧图片重复的次数,默认为1,若设置为0,表示永远循环下去。

12.6 SWT绘图

    SWT中的绘图功能通过org.eclipse.swt.graphics包中的GC对象来实现。任何实现了Drawable的类都可以进行绘制。

1. 使用绘制对象的方法
◆ 使用构造方法
GC(Drawable drawable)
GC(Drawable drawable, int style)
drawable为绘图接口对象。style可以为SWT.LEFT_TO_RIGHT、SWT.RIGHT_TO_LEFT、SWT.NONE。
以下所示的代码将shell窗口作为一个绘图对象构造GC对象:
GC gc = new GC(shell);
gc.dispose();

◆ 在绘图监听器对象中绘制
对于支持绘图功能的控件可以通过addPaintListener方法注册绘图监听器,来绘制图形。例如:
shell.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
    e.gc.drawOval(0, 0, 100, 100);
}
});

2. 绘制线条
◆ drawLine (int x1, int y1, int x2, int y2):绘制一条直线。(x1, y1)、(x2, y2)分别为两个点的坐标。
◆ drawPolyline(int[] pointArray):绘制多边线,其中pointArray为各个顶点的x和y坐标。
◆ drawPolygon(int[] pointArray):绘制多边形,其中pointArray为各个顶点的x和y坐标。
◆ drawRectangle (int x, int y, int width, int height):绘制矩形。(x, y)为左上角坐标,width为矩形的宽,height为矩形的高。
◆ drawOval (int x, int y, int width, int height):绘制椭圆。(x, y)为椭圆左上角的坐标,width为椭圆的宽,height为椭圆的高。如果宽和高相等,则绘制出圆形。
◆ drawRoundRectangle (int x, int y, int width, int height, int arcWidth, int arcHeight):绘制圆角矩形,(x, y)为左上角的坐标,width为宽,height为高。arcWidth和ardHeight为圆角弧度。
◆ drawArc (int x, int y, int width, int height, int startAngle, int arcAngle):绘制一段弧,startAngle为弧开始点的角度,范围在0~360,0表示坐标平面中x的正半轴,arcAngle所转过的弧度,若为正值,则表示逆时针,负值表示顺时针。
◆ drawPoint (int x, int y):绘制一个点。
◆ setLineStyle(int lineStyle):设置线条的样式。常量定义:SWT.LINE_*
◆ setLineWidth(int lineWidth):设置线条的粗细,以像素为单位。

3. 绘制字符
◆ drawString (String string, int x, int y):string为要显示的字符串,(x, y)为坐标。
举例如下:
     Font font = new Font(e.display, "Arial", 14, SWT.BOLD|SWT.ITALIC);
     e.gc.drawString("WH is as stubborn as a donkey", 30, 20);
     e.gc.setForeground(e.display.getSystemColor(SWT.COLOR_GREEN));
     e.gc.setFont(font);
     e.gc.setBackground(e.display.getSystemColor(SWT.COLOR_DARK_GRAY));
     e.gc.drawString("气死驴子", 30, 50);
     font.dispose();

显示效果:


◆ drawString (String string, int x, int y, boolean isTransparent):绘制字符串,isTransparent是否制定该文本透明显示。

4. 绘制填充图形
◆ fillArc (int x, int y, int width, int height, int startAngle, int arcAngle):填充扇形。
◆ fillOval (int x, int y, int width, int height):填充椭圆形。
◆ fillPolygon(int[] pointArray):填充多边线。
◆ fillRectangle (int x, int y, int width, int height):填充矩形。
◆ fillRoundRectangle (int x, int y, int width, int height, int arcWidth, int arcHeight):填充圆角矩形。
◆ fillGradientRectangle(int x, int y, int width, int height, boolean vertical):填充渐进的矩形。vertical表示渐近的方式是否垂直。举例如下:
     e.gc.setBackground(e.display.getSystemColor(SWT.COLOR_BLUE));
     e.gc.setForeground(e.display.getSystemColor(SWT.COLOR_CYAN));
     e.gc.fillGradientRectangle(5, 10, 100, 50, false);
    
     e.gc.setBackground(e.display.getSystemColor(SWT.COLOR_BLUE));
     e.gc.setForeground(e.display.getSystemColor(SWT.COLOR_CYAN));
     e.gc.fillGradientRectangle(5, 70, 100, 50, true);

显示效果:

5. 绘制图像
◆ drawImage(Image image, int x, int y):image为所绘制的图像,(x, y)为左上角的坐标。
◆ drawImage(Image image, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight):其中srcX、srcY、srcWidth、srcHeight为原始图像中的横坐标、纵坐标、宽度和高度。destX、destY、destWidth、destHeight为显示在控件中的横坐标、纵坐标、宽度和高度。
     e.gc.drawImage(i2, 10, 0, 80, 120, 5, 5, 80, 120);
显示效果: