系统资源包括颜色(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);
因为这种方式是从底层平台获得的颜色资源,这个资源不是我们自己创建的,只是被我们引用了,其他的对象有可能正在使用或者将要使用这个资源,释放这样的资源会带来不可预知的严重后果。
[color=red]JAVA的垃圾回收只能回收Java虚拟机中的对象,而对本地操作系统的对象是不能够自动释放的,所以对本地资源的释放一定要显式的释放掉。[/color]
释放资源的原则
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();
显示效果:
[img]http://dl.iteye.com/upload/attachment/332854/7fa3b809-c24a-305e-b45e-ebe4d5a4622e.jpg[/img]
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();
}
}
显示效果:
[img]http://dl.iteye.com/upload/attachment/332857/d613a1b8-9843-3836-9230-2760b25d9a59.jpg[/img]
◆ 创建画布时的样式还可以是: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
效果如下:
[img]http://dl.iteye.com/upload/attachment/332859/c12b8264-81eb-381c-ba18-c696257c34a0.jpg[/img]
◆ 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();
显示效果:
[img]http://dl.iteye.com/upload/attachment/332864/d2cb2ea1-7131-3e0d-a0c1-428b69087437.jpg[/img]
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();
显示效果:
[img]http://dl.iteye.com/upload/attachment/332866/b115b064-d0c9-30e2-b301-bee4c7a93b2a.jpg[/img]
◆ 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);
显示效果:
[img]http://dl.iteye.com/upload/attachment/332868/b6e252aa-0235-32f0-a0f9-16fa2deab86f.jpg[/img]
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);
显示效果:
[img]http://dl.iteye.com/upload/attachment/332870/0430abab-05fa-3d09-a5af-ad966ff0d6a0.jpg[/img]