3.1 图形API
3.1.1 Display
3.1.1.1 Display实例的创建
所有SWT程序开始运行时都必须首先得到一个Display对象,没有Display对象,SWT程序就无法和操作系统交互,创建Display对象的线程被称为UI线程。
常用函数:
getDefault()
首次调用创建一个Display实例,再次调用则获取已创建的Display实例。
getCurrent()
得到当前线程对应的Display实例。
注:
1、一个线程中不能同时有两个活动的Display实例存在,否则程序运行时会抛出一个SWT异常。
2、由于特殊要求需要创建多个同时活动的Display实例,则必须在不同的线程中创建它们,并使用Display的getCurrent函数得到当前线程对应的Display实例。
3.1.1.2 Display实例的释放
在SWT中,为了使资源管理方便而规定:当父资源被释放时,它要负责释放属于自己的子资源。Display实例是所有Shell的最高父资源,当一个Display实例被释放时,所有存在于这个UI线程中的Shell窗口都会被释放掉。
常用函数:
dispose()
释放Display实例。
3.1.1.3 Display的事件队列和事件循环
GUI程序运行的机制就是针对用户在界面上的每一个操作事件做出反应,即所谓“事件驱动”。操作系统为每一个GUI程序分配了一个事件队列,用于存放属于它的事件。每当用户操作鼠标或键盘时,操作系统会根据鼠标单击的位置、当前焦点窗口等信息决定应该把事件放到哪个GUI程序的队列中。
在GUI程序中,需要用一个循环不停地去读取自己的事件队列,每当检查到有新的事件时,就处理这个事件并做出适当的绘图动作反馈到用户。这就是事件循环。这个循环不停地将消息传递到GUI程序的各个部分。
Display事件循环中,同时处理着系统队列和一个应用程序级别的自定义队列中的事件,它从这些队列中读取事件,并将这些事件传递给相应的事件监听器来完成具体的实现。
常用函数:
readAndDispatch
该函数首先查看系统队列中是否有事件需要执行,如果有则处理系统队列中的事件,然后处理自定义底层事件队列中的事件;如果没有则查看自定义底层事件队列中是否有事件需要执行,否则返回false。
3.1.1.4 SWT程序中的多线程
程序执行耗时的计算会停止响应,为了解决这一问题,必须为非UI线程(后台线程)提供一个途径,使它能将需要执行的操作通知UI线程,这个通知动作被称为后台线程与UI线程同步。Display维护的自定义的事件队列就是用来供后台线程和UI线程同步的。后台线程用Runnable对象将绘图操作包装起来,然后将对象插入自定义事件队列中,这样Display执行消息循环时就会执行这些操作了。Display提供同步调用和异步调用两种方法向这个队列中插入事件。
常用函数:
syncExec(Runnable runnable)
同步调用方法会通知UI线程在下一次事件循环时执行runnable参数的run方法。调用这个方法的线程将被阻塞到runnable执行完成为止。如果参数是null,调用这个函数会唤醒休眠中的UI线程。
asyncExec(Runnable runnable)
异步调用方法会通知UI线程在下一次事件循环时执行runnable参数的run方法。调用这个方法的线程不会被阻塞,而且在runnable执行完成后不会得到通知。如果参数是null,调用这个函数会唤醒休眠中的UI线程。
示例代码:
button.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(final SelectionEvent e) {
Thread thread = new Thread() {
public void run() {
try {Thread.sleep(10000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
display.syncExec(new Runnable() {
public void run() {
button.setText("Execution Done");}});}};
thread.start();}});
注:
1、创建后台线程时,通常会将需要在Runnable的run()方法中访问的图形界面组件传递过去。但在代码被UI线程执行时,设计的组件有可能已经被释放了。因此在Runnable中需要对所用到的组件的状态加以判断,以防止产生“组件已被释放”的SWT异常。
3.1.1.5 监视器、边界和客户区域
监视器对象主要包含边界和客户区域两个部分,边界代表了这个监视器的屏幕大小,而客户区域则代表可以用来显示窗口的屏幕部分大小。一般来说,由于图形操作系统桌面上的任务栏占掉了一部分空间,客户区域的尺寸要小于边界的尺寸。使用监视器实例,可以得到当前用户屏幕的大小信息,程序可以根据这些信息安排窗口的尺寸及位置。
常用函数:
getMonitors()
取得与这个Display相连的所有监视器信息。
getPrimaryMonitor()
得到主监视器对象。
示例代码:
Display disp = Display.getDefault();
Monitor monitor = disp.getPrimaryMonitor();
System.out.println(monitor.getClientArea());
System.out.println(monitor.getBounds());
3.1.2 图形资源
SWT中常见的图形资源都继承自org.eclipse.swt.graphics.Resourse。自己创建的图形资源在程序结束时通过该图形资源的dispose()方法释放,通过Display取得的系统图形资源对象不能释放。
3.1.2.1 Color
org.eclipse.swt.graphics.Color类管理着操作系统中的颜色资源,使用RGB的色彩模型来描述颜色信息。
常用函数:
dispose()
当不在需要该对象时释放占用的系统资源。
示例代码:
Display display = Display.getDefault();
Color createdWhite = new Color(display,255,255,255);
Color systemBlack = display.getSystemColor(SWT.COLOR_BLACK);
while (!shell.isDisposed()) {
…
}
createdWhite.dispose();
display.dispose();
3.1.2.2 Image
一个Image对象代表了一个可用的图片信息。ImageData包含着设备无关的图象文件信息,如图像的尺寸,每个像素的颜色、透明度等内容。可以通过指定图像的尺寸和每一个像素的颜色值来生成一个ImageData,也可以从已有的文件或InputStream构造一个ImageData实例。
常用函数:
dispose()
当不在需要该对象时释放占用的系统资源。
示例代码:
Display display = Display.getDefault();
//获取Display内置的几个常用的Image对象,包括错误图标和警告图标等。
Image iconImage = display.getSystemImage(SWT.ICON_QUESTION);
//使用Image的构造函数指定路径读取一个InputStream来构造一个Image
Image buttonImage = new Image(display, UsingImage.class.getResourceAsStream("buttonImage.gif"));
//使用Image的构造函数指定路径读取一个图像文件来构造一个Image
Image image=new Image(display,”C:\\graphic.bmp”);
//使用ImageData类构造一个Image对象
Image image=new Image(display,imageData);
3.1.2.2 Font
Font资源管理着显示文本时所使用的字体、字号、格式等各种样式。可以。和其他图形资源一样,自己创建的字体用完后一定要释放,而使用系统字体时不能释放。
常用函数:
dispose()
当不在需要该对象时释放占用的系统资源。
示例代码:
Display display = Display.getDefault();
//得到系统内置的字体
Font sysFont = display.getSystemFont();
//通过指定字体名称、高度和格式创建一个字体
Font createdTahoma = new Font(display, "Tahoma", 10,
联系客服