`
edgar108
  • 浏览: 32571 次
  • 性别: Icon_minigender_1
社区版块
存档分类
最新评论

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

 

未完待续。

  • 大小: 9.6 KB
分享到:
评论

相关推荐

    Eclipse从入门到精通 陈刚 源码

    “插件开发篇”介绍了Eclipse插件开发的各个步骤,并给出了一个基于数据库开发和面向对象分析设计的完整插件实例;“Web开发篇”以Tomcat+Lomboz+Hibernate为开发环境,详述了其下载、安装、配置和开发的全过程。 ...

    java源码包---java 源码 大量 实例

    内容索引:Java源码,初学实例,二进制,文件复制  Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java...

    java源码包2

    内容索引:Java源码,初学实例,二进制,文件复制  Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java...

    java源码包3

    内容索引:Java源码,初学实例,二进制,文件复制  Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java...

    java源码包4

    内容索引:Java源码,初学实例,二进制,文件复制  Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java...

    JAVA上百实例源码以及开源项目源代码

    内容索引:Java源码,初学实例,二进制,文件复制  Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java...

    eclipse.rcp应用系统开发方法与实战(含源码)

    内附有一个高校收费分析系统实例源码,用hibernate 与rcp结合使用,对初学者来说很实用的,特别是想了解如何在桌面程序使用jface,swt并与hibernate结合处理数据库使用方面很到位。

    JAVA上百实例源码以及开源项目

    内容索引:Java源码,初学实例,二进制,文件复制  Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java...

    成百上千个Java 源码DEMO 4(1-4是独立压缩包)

    Java二进制IO类与文件复制操作实例 16个目标文件 内容索引:Java源码,初学实例,二进制,文件复制 Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系...

    成百上千个Java 源码DEMO 3(1-4是独立压缩包)

    Java二进制IO类与文件复制操作实例 16个目标文件 内容索引:Java源码,初学实例,二进制,文件复制 Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系...

    Eclipse开发入门与项目实践 源代码

    第二部分 项目实践 第9章 Shopping Online网站概述及设计方案 296 9.1 Shopping Online购物在线网站总体描述 296 9.1.1 项目背景 297 9.1.2 网站开发基本流程 297 9.2 方案设计 298 9.2.1 设计原则 ...

    Visual C++ 编程资源大全(源码 窗体)

    用到了CSplitterWnd::DeleteView()和CSplitterWnd::CreateView()等成员函数(35KB)&lt;END&gt;&lt;br&gt;44,swt.zip DOS下仿WIN95界面及图标编辑器源程序(498k C&ASM 作者:添翼虎)(499KB)&lt;END&gt;&lt;br&gt;45,menutest.zip 定制WIN...

    java基础案例与开发详解案例源码全

    3.3.2 经验之谈-常见错误的分析与处理40 3.3.3 Java标识符命名规则41 3.3.4 关键字42 3.3.5 常量42 3.4 运算符43 3.4.1 算术运算符43 3.4.2 赋值操作符45 3.4.3 关系操作符47 3.4.4 逻辑操作符48 3.4.5 位操作符49 ...

    Eclipse+Web开发从入门到精通(实例版)

    1.5 SWT 界面开发实例... 13 1.5.1 使用Shell 创建窗口... 13 1.5.2 简单的用户密码验证器... 16 1.5.3 文件选择器... 19 第 2 章 在 Eclipse 中进行重构... 22 2.1 重命名实例... 22 2.2 移动实例... ...

Global site tag (gtag.js) - Google Analytics