继续上次的。
上次程序中的部分代码:
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程序,从头到尾的执行流程我们已经有了初步的认识!
未完待续。