`

SWT/JFace专题 --- SWT API 结构

 
阅读更多
SWT API 结构

1.布局类(layout)
布局类负责者控件在窗口中的摆放位置,并在窗口大小变化时重新摆放它们
它主要由布局管理器组成。布局管理器将窗口的布局设计与窗口中控件的具体业务逻辑分离开来,使得编程工作的模块划分更为清晰,也使得开发者可以根据需要动态地改变一个窗口中控件的摆放方式。
所有的布局管理器都必须继承org.eclipse.swt.widgets.Layout。SWT自带的布局管理器有:FillLayout,GridLayout,StackLayout,RowLayout,FormLayout。另外,可以根据需要自定义布局管理器(继承Layout 抽象类)。
public abstract class Layout {
/**
 * Computes and returns the size of the specified
 * composite's client area according to this layout.
 */
protected abstract Point computeSize (Composite composite, int wHint, int hHint, boolean flushCache);

/**
 * Instruct the layout to flush any cached values
 * associated with the control
 */
protected boolean flushCache (Control control) {
	return false;
}

/**
 * Lays out the children of the specified composite
 * according to this layout.
 */
protected abstract void layout (Composite composite, boolean flushCache);
}

2.组件类(Widgets)
组件分为控件(Control)和Item两大部分。控件是项目的主体,Item依赖于控件并为它们提供附加的功能。组件类负责显示窗口以及其中可以和用户交互的按钮,文本框等各种组件,是SWT API的核心部分。

1)Control(控件)

所有的控件都是从org.eclipse.swt.widget.Control继承来。
最上层的Widget类直接继承Object,是SWT中所有和窗口相关的部件的父类,它为所有窗口组件提供了创建对象(申请资源)、释放资源和事件监听的功能。

Widget有两个比较重要的子类:Control类是所有控件的父类;Item类则是控件的辅助部分,它代代表了复杂控件中的某一“项”,如表格控件中的一行就是由TableItem来表示的。

Button、Label等简单控件都直接继承自Control控件;
Scrollable代表拥有滚动条的控件,它的子类有Text和Composite等;
Composite被称为容器控件,Composite容器是SWT控件体系中最基本的容器类型,是其他所有容器类型的父类。这类控件主要的用途不是与用户交互,而是将容纳于其中的其他控件在界面上分组摆放,它的子类有Table、Tree等可以用来显示复杂数据结构的控件。Composite的设计思想基于设计模式中的Composite模式,利用容器来包含其他容器或基本控件,可以将控件组合成树状结构。

Canvas是允许程序员使用画点、线等基本图形操作在其中直接绘图的控件;Shell间接继承自Canvas类。
Item(条目)
Item依赖于控件并为它们提供附加的功能,如Image,Text等
SWT中提供的Item实现类有:

所有的Item都需实现抽象类Item,源码如下:
/**
 * This class is the abstract superclass of all non-windowed
 * user interface objects that occur within specific controls.
 * For example, a tree will contain tree items.
 */
public abstract class Item extends Widget {
	String text;
	Image image;

/**
 * Constructs a new instance of this class given its parent
 * and a style value describing its behavior and appearance.
 */
public Item (Widget parent, int style) {
	super (parent, style);
	text = "";
}
... ...
geters/seters/other methods
... ...
}
3.事件类(Events)
事件类负责者将控件的消息发送到操作系统中,并将操作系统的消息传递给控件
事件类主要负责消息的专递。事件是图形界面程序与用户交互的核心,SWT的事件处理机制采用的是事件监听(Event Listener)的结构,即使用Observer(观察者)的设计模式来处理事件。这种模式使得事件的发送方和接受方之间维持了极低的耦合度,因而具有良好的可扩展性,也是很多图形框架处理事件的模式。

对某个对象上的某个事件感兴趣的话,就需要在对象上注册一个对应事件的监听器。当事件发生时,所有在对象上注册过的此事件监听器都会收到通知。
监听器是一个接口,其中包含的每一个方法都对应了某事件的发生,而其参数则包含了所发生的事件的上下文信息。

在SWT中,Listener接口扮演了观察器接口的角色,而所有的窗口组件的父类--Widget类则是事件源。创建了Listener实例后,可以调用Widget.addListener(int eventType,Listener listener) 方法将它添加到界面组件上,也可以removeListener(int eventType,Listener listener)将它从组件上删除。

监听器的工作原理:
(1)Event Source,事件源就是一个可能产生事件的对象,它维护了一个事件监听器队列。
(2)监听器是一个接口,如果对某个对象的某种事件感兴趣,需要实现一个事件对应的监听器,并将它加到目标对象的监听器队列中。
(3)当某个特定事件在事件源上发生时,事件源会从监听器队列中对这个事件感兴趣的监听器,并依此通知它们事件发生。
(4)对事件感兴趣的对象。当事件发生时这些对象会通过监听器接口接到通知。
使用监听器的优点在于事件源不必关心具体的监听者是谁。这种结构使得模块之间耦合度较低,易于维护和修改。
------
在SWT中,可以用代码模拟键盘和鼠标事件。首先创建一个org.eclipse.swt.widgets.Event实例,并使用Display.post()将它添加到操作系统的事件队列中,程序会把这个事件等同于真正来自操作系统的事件加以处理。
这个模型功能在开发图形界面程序的自动化测试时有很大的帮助。
例子:
Event event= new Event();
event.type=SWT.KeyDown;
event.keyCode=SWT.SHIFT;
display.post(event);

4.图形类(Graphics)
图形类负责调用下层的JNI函数完成绘图命令,以及将通过JNI传来的操作系统消息转换成事件传达到上层的控件类。它在面向对象风格的SWT API和面向过程的C风格底层API之间起转换作用。

图形类在SWT API的最下层,主要由两部分组成:Resource和Display。
在编写图形界面程序时,所有的控件、图片、字体等图形对象都会消耗系统资源。因为系统上资源有限,为了保证资源被最大化的运用,程序负责及时释放这些资源。
资源在SWT中由Resource类的子类,如Font,Image等所使用,而分配或释放它们的操作则是由Display负责和操作系统交互而完成。Display将不同操作系统中对事件循环的实现封装成为SWT的统一事件循环机制,它提供了丰富的方法用来访问操作系统的资源,因此它是SWT与底层操作系统交互的桥梁。

SWT中,创建Display实例的线程被称为界面线程(UI Thread)。界面线程具有以下特征:
1)Display的事件循环必须在界面线程中执行。
2)所有通过Display完成的绘图操作都只能在界面线程中执行。
3)在同一个界面线程中,不能同时创建多个Display对象。

为什么会有这些特征(或者限制)呢?这首先需要了解一下GUI图形界面程序运行的基本原理。GUI程序运行的机制就是针对用户界面的每一个操作事件做出响应,即所谓的“事件驱动”。操作系统为每一个GUI程序分配一个事件队列,用于存放它的事件。每当用户操作鼠标或键盘时,操作系统会根据鼠标单击的位置、当前的焦点窗口等信息决定把事件放到那一个队列中。而在GUI程序中,需要用一个循环,不停地去读取自己的事件队列,每当检查到一个新的事件,就处理该事件并做出适当的绘图动作反馈到用户。这就是事件循环(Event Loop)。这个循环不停地将消息传递到GUI程序的各个部分,像一个水泵,因此称为“消息泵”。
事件循环机制是GUI程序的心脏,GUI事件处理基本原理如下:
(1)当用户操作鼠标、键盘时,操作系统会产生一个新的消息事件;
(2)系统会根据鼠标单击的位置等各种信息决定消息应该发送给哪个应用程序;
(3)在操作系统中,每个GUI程序都拥有自己的消息队列,存放着发送给它的鼠标、键盘等操作消息;
(4)SWT采用了Java语言编写的事件循环,通过JNI读取队列中的消息并处理它们;

在目前主流的操作系统中,对事件循环的处理存在着两种模型,一种是单线程模型,这种模型只允许程序中的一个线程监听事件消息并作出绘图动作;另一种是允许程序中的所有线程自由访问程序中的事件队列的东线程模型。为了保持平台兼容性,降低实现的复杂度,SWT采用单线程模型管理事件循环和绘图操作。这也正是存在上面三条限制的重要原因。

采用单线程模型的好处主要是,首先,使用单线程模型不仅能够很好的管理好内存,减少操作系统中的线程数,也能够促使程序将绘图操作放在一起,实现业务逻辑和绘图操作的分离,结构清晰,方便调试;其次,在许多主流操作系统中,图形操作并不是简单的依此执行,专门的图形引擎会对这些操作进行优化以提高效率。将绘图操作集中在同一个线程中提交,有利于优化引擎最大程度地发挥作用。

在SWT中,没有系统资源的自动分配和释放的机制,资源的管理是由程序员手动完成的。对于资源的使用和释放,有两个原则:谁分配谁释放;释放父资源时,所有的子资源一起释放。

5.其他组件(Browser,Printing,OpenGL,Drag&Drop)这些组件提供打印,拖放操作等辅助功能。
  • 大小: 13.2 KB
  • 大小: 8.7 KB
  • 大小: 9.9 KB
  • 大小: 23.5 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics