[Eclipse笔记]在SWT中有效的管理图形系统资源

笔记|图形

本文部分内容和灵感来自eclipse.org网站,特此声明。更多内容,请参考:

http://eclipse.org/articles/Article-SWT-Design-2/SWT-Design-2.html

 

由于SWT直接跟操作系统打交道,所以我们需要在处理系统的图形资源时格外小心,以免不必要的资源泄漏。所幸SWT提供了很好的资源管理机制,我们绝大多数情况下需要做的只是确保两条原则:

第一条原则 – 谁分配谁销毁

第二条原则 – 父控件销毁的同时销毁子控件

 

下面我们分别来看一看这两条在实际中是如何体现的。

先看第一条原则。乍一看这似乎是废话,但是在实际中往往并非那么简单。首先,构造方法不等于分配资源,实际上分配资源可以发生在一个类中的任何地方以及一个对象生命周期的任何时候,只要你的代码告诉操作系统这样做。你必须保证所有由你分配的资源当你不再使用时调用其dispose()方法;同时你也必须保证所有不是由你分配的资源不要随便调用其dispose()方法,否则很可能会影响到实际分配的那段相关代码的正常工作。好消息是,为了明确和简化这第一条原则所规定的分工,SWT在设计之初就确定下来,所有基于系统资源的SWT类都在其构造方法中完成所有所需的资源分配,在其他方法中则没有任何分配系统资源的动作,所以我们可以幸运的这样看待SWT的资源管理:如果你调用了某个SWT类的构造方法,那么就由你来调用其dispose()方法释放资源;如果你没有调用某个SWT类的构造方法,即便你使用了这个类的实例,也不应该由你来调用其dispose()方法。就是这么明确。

比方讲,你new了一个Font对象,那么当你不再需要它时,就应该调用dispose();如果你通过某个控件的getFont()方法取得一个Font对象并使用后,你不应该去销毁它,而应该交给那个具体的控件去处理。

对于第二条原则,SWT有一个很好的机制去支持它,那就是,所有的SWT控件,具体讲,Composite类及其子类的实例,都必须有一个父控件,这个父控件的引用在子控件的构造方法中被传入。需要注意的是,所有这些控件的不带参数的构造方法都只有默认访问级别,于是我们不能在自己的SWT程序中直接调用这样的默认构造方法而只能提供一个父控件的引用,而在Widget类(Composit的父类)的带参数构造方法中,它会调用如下方法:

void checkParent (Widget parent) {       if (parent == null) error (SWT.ERROR_NULL_ARGUMENT);       parent.checkWidget ();}
进而:

protected void checkWidget () {       Display display = this.display;       if (display == null) error (SWT.ERROR_WIDGET_DISPOSED);       if (display.thread != Thread.currentThread ()) error (SWT.ERROR_THREAD_INVALID_ACCESS);       if ((state & DISPOSED) != 0) error (SWT.ERROR_WIDGET_DISPOSED);}
这样的检查保证了任何控件在创建时都有父控件。当我们调用某个Composite的dispose()方法时,它会调用:

void releaseChildren () {       Control [] children = _getChildren ();       for (int i=0; i<children.length; i++) {              Control child = children [i];              if (!child.isDisposed ()) child.releaseResources ();       }}
其中的_getChildren()方法通过OS对象的方法遍历控件的子控件,然后汇总到一起分别调用releaseResources()方法释放控件和句柄。

回到上次的SimplestSWT的例子:

package sean.test.swt;import org.eclipse.swt.widgets.Display;import org.eclipse.swt.widgets.Shell;public class SimplestSWT {    public static void main(String[] args) {        Display display = new Display();        Shell shell = new Shell(display);        shell.pack();        shell.open();        while (!shell.isDisposed()) {            if (!display.readAndDispatch()) {                display.sleep();            }        }        display.dispose();    }}
 

这当中,Display是一个顶层的设备,它继承自Device类,而Device类实现了Drawable接口。Shell的父类是Decoration,而Decoration继承自Canvas,Canvas继承自Composite,最终这条继承链一直连到Widget类。我们在创建Shell示例的时候,需要告诉构造方法它的父控件是什么,在这里就是display。于是当我们最后调用display.dispose()时,虽然我们没有明确写shell.dispose(),我们的Shell实例也随之销毁了。

这就是SWT的资源管理机制,稍有例外的是MenuItem的setMenu()方法和Control的setMenu()方法,它们通过显式调用setMenu的方式注册自己的父控件。

 

时间: 2024-10-26 06:07:46

[Eclipse笔记]在SWT中有效的管理图形系统资源的相关文章

[Eclipse笔记]配置SWT开发环境

笔记   本文假定读者使用Windows操作系统+JDK1.4,其他平台和JDK版本应该也是八九不离十. 为了编译和运行SWT程序,我们有两种选择:1- 使用Eclipse SDK:2- 下载单独的SWT二进制文件和源文件. 随Eclipse SDK,我们可以在它的plugins目录下找到SWT的二进制文件,通常的目录名称是:org.eclipse.swt.win32_xxxx,后缀是版本号,在这个目录下有os和ws两个子目录,内容分别是SWT的JNI库和swt.jar. 如果不是使用Eclip

[Eclipse笔记]一个最简单的SWT程序

笔记|程序 我们来看一段最简单的SWT程序是什么样子:package sean.test.swt;import org.eclipse.swt.widgets.Display;import org.eclipse.swt.widgets.Shell;public class SimplestSWT {    public static void main(String[] args) {        Display display = new Display();        Shell s

《SQL Server企业级平台管理实践》读书笔记——SQL Server中数据文件空间使用与管理

原文:<SQL Server企业级平台管理实践>读书笔记--SQL Server中数据文件空间使用与管理 1.表和索引存储结构 在SQL Server2005以前,一个表格是以一个B树或者一个堆(heap)存放的.每个B树或者堆,在sysindexes里面都有一条记录相对应.SQL Server2005以后,引入了分区表的概念(Table Partition),在存储组织上,现有的分区基本上替代了原来表格的概念,原先表的概念成为了一个逻辑概念.一个分区就是一个B树或者一个堆.而一张表格则是一个

《SQL Server企业级平台管理实践》读书笔记——SQL Server中收缩数据库不好用的原因

原文:<SQL Server企业级平台管理实践>读书笔记--SQL Server中收缩数据库不好用的原因 数据库管理员有时候需要控制文件的大小,可能选择收缩文件,或者把某些数据文件情况以便从数据库里删除. 这时候我们就要使用到DBCC SHRINKFILE命令,此命令的脚本为: DBCC SHRINKFILE ( { file_name | file_id } { [ , EMPTYFILE ] | [ [ , target_size ] [ , { NOTRUNCATE | TRUNCATE

SWT中关于FocusListener的问题

问题 在SWT中FocusListener可以用来监听一个textfield是否被选中,在下面的程序里,我在两个text上加了FocusListener,功能是当text被选中时,上面的文字会呈全选状态.我不知道为什么只对第一个有效?后来才发现是因为两个text的类型不一样.只是对SWT.SINGLE的text,好象selectAll()无效 . //TextField1.javaimport org.eclipse.swt.SWT;import org.eclipse.swt.events.F

Eclipse安装和SWT/JFace项目的配置

项目 下载eclipse3.0.1版本: 确认已经安装了java jdk,使用jdk1.4以上版本: 将eclipse3.0.1版本下载文件解压: 配置${eclipse}/eclipse.exe快捷方式,"${eclipse}/eclipse.exe -vm %JAVA_HOME%/bin/javaw.exe": 如果使用VE的话,配置如下: 下载并安装EMF build 2.0.1: 下载并安装GEF Build 3.0.1: 下载并安装VE:SWT/JFace项目需要引入的jar

[Eclipse笔记]作为Java IDE的Eclipse有多流行?看看今年TheServerSide的Java研讨会上做的一个调查。

server|笔记 今天无意中在TheServerSide.com上闲逛时发现一条有趣的调查结果.作为今年TheServerSide举办的Java研讨会活动的一部分,每天上午组委会都会向与会代表做一些问卷调查,其中有一项叫做:What is your preferred Java IDE?你最喜欢的Java IDE是什么?下面是这项调查的结果:What is your preferred Java IDE?     Eclipse 53.3% emacs 2.1% IDEA 19.8% Java

在SWT中使用OLE操作Excel(三)——设置单元格背景色

packagecom.jrkui.example.excel; import org.eclipse.swt.SWT;import org.eclipse.swt.layout.FillLayout;import org.eclipse.swt.ole.win32.OLE;import org.eclipse.swt.ole.win32.OleAutomation;import org.eclipse.swt.ole.win32.OleClientSite;import org.eclipse.

详解Visual Studio 2010中的扩展管理器

扩展能够为核心应用程序提供附加的功能或者自定义设置.在很多应用程序中这都是很流行的,包括流行的web浏览器IE和Firefox.微软的Office.媒体播放器.Photoshop.Eclipse.Visual Studio等等.其中有些可能比较新奇,而针对开发工具--像Eclipse和Visual Studio--的扩展让开发者的生产力得到了显著提高. Visual Studio早期的版本是构建在COM技术之上的.而Visual Studio的主要扩展方式插件是通过COM接口实现的.随着时间的变