SWT源码分析(2)
继续上次的。
上次程序中的部分代码:
Text hello = new Text(shell, SWT.MULTI); hello.addMouseListener(new MouseListener() { @Override public void mouseUp(MouseEvent e) { // TODO Auto-generated method stub MessageBox box = new MessageBox(shell); box.setMessage("内容"); box.setText("标题"); box.open(); } @Override public void mouseDown(MouseEvent e) { // TODO Auto-generated method stub } @Override public 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程序,从头到尾的执行流程我们已经有了初步的认识!
未完待续。