SWT源码分析(二)
继续上次的。
?
上次程序中的部分代码:
?
Text hello = new Text(shell, SWT.MULTI); hello.addMouseListener(new MouseListener() {@Overridepublic void mouseUp(MouseEvent e) {// TODO Auto-generated method stubMessageBox box = new MessageBox(shell);box.setMessage("内容");box.setText("标题");box.open();}@Overridepublic void mouseDown(MouseEvent e) {// TODO Auto-generated method stub}@Overridepublic void mouseDoubleClick(MouseEvent e) {// TODO Auto-generated method stub}});?在Swing中也是这样,如果我们想对某个控件的事件进行相应,就在这个控件上加上一些listener。在listener中写具体的操作。按住Ctrl进入addMouseListener方法中:
?
public void addMouseListener (MouseListener listener) {checkWidget ();if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);TypedListener typedListener = new TypedListener (listener);addListener (SWT.MouseDown,typedListener);addListener (SWT.MouseUp,typedListener);addListener (SWT.MouseDoubleClick,typedListener);}这里创建了一个TypedListener 对象,然后将我们自定义的listener放入个eventListener 中:
?
public TypedListener (SWTEventListener listener) {eventListener = listener;}??
?可知AddMouseListener是Controll类中的方法,方法中有调用了Widget类中的addListener方法:
?
public void addListener (int eventType, Listener listener) {checkWidget();if (listener == null) error (SWT.ERROR_NULL_ARGUMENT);_addListener (eventType, listener);}?addListener方法中又调用了本类中的_addListener方法:
?
void _addListener (int eventType, Listener listener) {if (eventTable == null) eventTable = new EventTable ();eventTable.hook (eventType, listener);}?可见,最后的操作是调用hook函数把事件类型和监听器listener放入了一个EventTable中:
?
public void hook (int eventType, Listener listener) {if (types == null) types = new int [GROW_SIZE];if (listeners == null) listeners = new Listener [GROW_SIZE];int length = types.length, index = length - 1;while (index >= 0) {if (types [index] != 0) break;--index;}index++;if (index == length) {int [] newTypes = new int [length + GROW_SIZE];System.arraycopy (types, 0, newTypes, 0, length);types = newTypes;Listener [] newListeners = new Listener [length + GROW_SIZE];System.arraycopy (listeners, 0, newListeners, 0, length);listeners = newListeners;}types [index] = eventType;listeners [index] = listener;}?hook函数中前面是一些判断,确定本次要放入的index是最后一个放入的事件之后加1的位置,如果是数组的最后一个index,会扩充现有的数组,最后把事件类型和listener放入对应数组。
?
SWT的控件继承关系如下:

可见,本例子中的Text是Widget和子类,Text对象中也必然有一个eventTable。
恩,现在我已经知道了每当一个控件调用addXXXListener时,就是往自己的eventTable中注册了要监听的事件和对应的操作。
?
现在回到上一篇文章中停留的地方-----runDeferredEvents 方法:
?
boolean runDeferredEvents () {boolean run = false;/** Run deferred events. This code is always* called in the Display's thread so it must* be re-enterant but need not be synchronized.*/while (eventQueue != null) {/* Take an event off the queue */Event event = eventQueue [0];if (event == null) break;int length = eventQueue.length;System.arraycopy (eventQueue, 1, eventQueue, 0, --length);eventQueue [length] = null;/* Run the event */Widget widget = event.widget;if (widget != null && !widget.isDisposed ()) {Widget item = event.item;if (item == null || !item.isDisposed ()) {run = true;widget.sendEvent (event);}}/** At this point, the event queue could* be null due to a recursive invocation* when running the event.*/}/* Clear the queue */eventQueue = null;return run;}?在得到了event之后,会调用对应widget中的sendEvent方法,本程序中的widget就是Text。sendEvent 方法如下:
?
void sendEvent (Event event) {Display display = event.display;if (!display.filterEvent (event)) {if (eventTable != null) eventTable.sendEvent (event);}}?可见调用的是eventTable中的sendEvent方法:
?
public void sendEvent (Event event) {if (types == null) return;level += level >= 0 ? 1 : -1;try {for (int i=0; i<types.length; i++) {if (event.type == SWT.None) return;if (types [i] == event.type) {Listener listener = listeners [i];if (listener != null) listener.handleEvent (event);}}} finally {boolean compact = level < 0;level -= level >= 0 ? 1 : -1;if (compact && level == 0) {int index = 0;for (int i=0; i<types.length; i++) {if (types [i] != 0) {types [index] = types [i];listeners [index] = listeners [i];index++;}}for (int i=index; i<types.length; i++) {types [i] = 0;listeners [i] = null;}}}}?其中的关键代码是:
?
if (types [i] == event.type) {Listener listener = listeners [i];if (listener != null) listener.handleEvent (event);}?遍历eventTable,找到对应事件的listener,然后调用listener中的HandleEvent方法,方法的具体实现就在一开头见过的TypedListener中:
?
public void handleEvent (Event e) {switch (e.type) { ......case SWT.MouseDown: {((MouseListener) eventListener).mouseDown(new MouseEvent(e));break;}case SWT.MouseDoubleClick: {((MouseListener) eventListener).mouseDoubleClick(new MouseEvent(e));break;}case SWT.MouseUp: {((MouseListener) eventListener).mouseUp(new MouseEvent(e));break;}case SWT.Move: {((ControlListener) eventListener).controlMoved(new ControlEvent(e));break;}case SWT.Paint: {/* Fields set by Control */PaintEvent event = new PaintEvent (e);((PaintListener) eventListener).paintControl (event);e.gc = event.gc;break;} ......}}?switch里面的case语句很多,省略了一些。可见对于本程序中的mouseup事件,将一开始创建TypedListener传入的listener,又强制转换为了MouseListener,最后调用程序中定义的mouseup方法,调用程序员写的实际逻辑。
?
到此为止,对于这个基本的SWT程序,从头到尾的执行流程我们已经有了初步的认识!
?
未完待续。