|
![]() |
名片设计 CorelDRAW Illustrator AuotoCAD Painter 其他软件 Photoshop Fireworks Flash |
|
本文部分内容和灵感来自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的方法注册自己的父控件。 返回类别: 教程 上一教程: Mini Java编译器(二) 下一教程: 用Swing的Jtable类让数据看起来更干净 您可以阅读与"[Eclipse笔记]在SWT中有效的治理图形系统资源"相关的教程: · [Eclipse笔记]一个最简朴的SWT程序 · [Eclipse笔记]SWT设计思路 · [Eclipse笔记]配置SWT开发环境 · [Eclipse笔记]关于3.1M5a的性能 · 使用LUCENE进行全文检索(二)-得到有效的内容 |
![]() ![]() |
快精灵印艺坊 版权所有 |
首页![]() ![]() ![]() ![]() ![]() ![]() ![]() |