SWT源码分析(二)

继续上次的。

 

上次程序中的部分代码:

 

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程序,从头到尾的执行流程我们已经有了初步的认识!

 

未完待续。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值