继续上次的。
上次程序中的部分代码:
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程序,从头到尾的执行流程我们已经有了初步的认识!
未完待续。
相关推荐
“插件开发篇”介绍了Eclipse插件开发的各个步骤,并给出了一个基于数据库开发和面向对象分析设计的完整插件实例;“Web开发篇”以Tomcat+Lomboz+Hibernate为开发环境,详述了其下载、安装、配置和开发的全过程。 ...
内容索引:Java源码,初学实例,二进制,文件复制 Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java...
内容索引:Java源码,初学实例,二进制,文件复制 Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java...
内容索引:Java源码,初学实例,二进制,文件复制 Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java...
内容索引:Java源码,初学实例,二进制,文件复制 Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java...
内容索引:Java源码,初学实例,二进制,文件复制 Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java...
内附有一个高校收费分析系统实例源码,用hibernate 与rcp结合使用,对初学者来说很实用的,特别是想了解如何在桌面程序使用jface,swt并与hibernate结合处理数据库使用方面很到位。
内容索引:Java源码,初学实例,二进制,文件复制 Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java...
Java二进制IO类与文件复制操作实例 16个目标文件 内容索引:Java源码,初学实例,二进制,文件复制 Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系...
Java二进制IO类与文件复制操作实例 16个目标文件 内容索引:Java源码,初学实例,二进制,文件复制 Java二进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系...
第二部分 项目实践 第9章 Shopping Online网站概述及设计方案 296 9.1 Shopping Online购物在线网站总体描述 296 9.1.1 项目背景 297 9.1.2 网站开发基本流程 297 9.2 方案设计 298 9.2.1 设计原则 ...
用到了CSplitterWnd::DeleteView()和CSplitterWnd::CreateView()等成员函数(35KB)<END><br>44,swt.zip DOS下仿WIN95界面及图标编辑器源程序(498k C&ASM 作者:添翼虎)(499KB)<END><br>45,menutest.zip 定制WIN...
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 ...
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 移动实例... ...