SWT中事件的触发借助于底层操作系统,因此首先贴出windows下的系统函数:
LRESULT CALLBACK WindowProc(
_In_ HWND hwnd,
_In_ UINT uMsg,
_In_ WPARAM wParam,
_In_ LPARAM lParam
);
当用户单击某个控件时首先由操作系统调用Display的windowProc方法
/*
*handle为系统事件的句柄140051169515536
*userata为事件类型(注意:这里事件指的是系统事件)
*/
long /*int*/ windowProc (long /*int*/ handle, long /*int*/ user_data) {
Widget widget = getWidget (handle);//根据句柄获得相应的控件,本例子中为Button
if (widget == null) return 0;
return widget.windowProc (handle, user_data);//调用widget的windowProc函数,
//该函数并没有被子类Button重写,因此Button继承了父类的函数
}
Widget的windowProc函数
//根据系统事件类型(user_data),调用相应的处理函数,这里为Button重写的gtk_clicked函数。
long /*int*/ windowProc (long /*int*/ handle, long /*int*/ user_data) {
switch ((int)/*64*/user_data) {
case ACTIVATE: return gtk_activate (handle);
case CHANGED: return gtk_changed (handle);
case CLICKED: return gtk_clicked (handle);
case CREATE_MENU_PROXY: return gtk_create_menu_proxy (handle);
case DAY_SELECTED: return gtk_day_selected (handle);
case DAY_SELECTED_DOUBLE_CLICK: return gtk_day_selected_double_click (handle);
case HIDE: return gtk_hide (handle);
case GRAB_FOCUS: return gtk_grab_focus (handle);
case MAP: return gtk_map (handle);
case MONTH_CHANGED: return gtk_month_changed (handle);
case OUTPUT: return gtk_output (handle);
case POPUP_MENU: return gtk_popup_menu (handle);
case PREEDIT_CHANGED: return gtk_preedit_changed (handle);
case REALIZE: return gtk_realize (handle);
case START_INTERACTIVE_SEARCH: return gtk_start_interactive_search (handle);
case SELECT: return gtk_select (handle);
case SELECTION_DONE: return gtk_selection_done (handle);
case SHOW: return gtk_show (handle);
case VALUE_CHANGED: return gtk_value_changed (handle);
case UNMAP: return gtk_unmap (handle);
case UNREALIZE: return gtk_unrealize (handle);
default: return 0;
}
}
以下是Button类的gtk_clicked函数
long /*int*/ gtk_clicked (long /*int*/ widget) {
if ((style & SWT.RADIO) != 0) {//当Button类型为单选按钮时
if ((parent.getStyle () & SWT.NO_RADIO_GROUP) != 0) {
setSelection (!selected);
} else {
selectRadio ();
}
} else {
if ((style & SWT.CHECK) != 0) {//当Button类型为多选按钮时
if (grayed) {
if (OS.gtk_toggle_button_get_active (handle)) {
OS.gtk_toggle_button_set_inconsistent (handle, true);
} else {
OS.gtk_toggle_button_set_inconsistent (handle, false);
}
}
}
}
sendSelectionEvent (SWT.Selection);
return 0;
}
void sendSelectionEvent (int eventType) {
sendSelectionEvent (eventType, null, false);
}
void sendSelectionEvent (int eventType, Event event, boolean send) {
if (eventTable == null && !display.filters (eventType)) {
return;
}
if (event == null) event = new Event ();
//返回当前GTK+处理事件的副本,详细请参考http://www.gtk.org/api/2.6/gtk/gtk-General.html
//TODO:关于底层GTK+的东西,还需要扩展
long /*int*/ ptr = OS.gtk_get_current_event ();
if (ptr != 0) {
GdkEvent gdkEvent = new GdkEvent ();
OS.memmove (gdkEvent, ptr, GdkEvent.sizeof);
switch (gdkEvent.type) {
case OS.GDK_KEY_PRESS:
case OS.GDK_KEY_RELEASE:
case OS.GDK_BUTTON_PRESS:
case OS.GDK_2BUTTON_PRESS:
case OS.GDK_BUTTON_RELEASE: {
int [] state = new int [1];
OS.gdk_event_get_state (ptr, state);
setInputState (event, state [0]);
break;
}
}
OS.gdk_event_free (ptr);
}
sendEvent (eventType, event, send);
}
//根据事件类型封装java中的事件
void sendEvent (int eventType, Event event, boolean send) {
if (eventTable == null && !display.filters (eventType)) {
return;
}
if (event == null) event = new Event ();
event.type = eventType;
event.display = display;
event.widget = this;
if (event.time == 0) {
event.time = display.getLastEventTime ();
}
if (send) {
sendEvent (event);//将消息直接send到窗口过程
} else {
display.postEvent (event);//将消息post到一个先进先出的队列中(消息队列)
}
}
////将消息post到一个先进先出的队列中(消息队列)
void postEvent (Event event) {
/*
* Place the event at the end of the event queue.
* This code is always called in the Display's
* thread so it must be re-enterant but does not
* need to be synchronized.
*/
if (eventQueue == null) eventQueue = new Event [4];
int index = 0;
int length = eventQueue.length;
//寻找消息队列中的一个空位置放入消息
while (index < length) {
if (eventQueue [index] == null) break;
index++;
}
//如果当前消息队列已满,新建一个长度+4的消息队列
if (index == length) {
Event [] newQueue = new Event [length + 4];
System.arraycopy (eventQueue, 0, newQueue, 0, length);
eventQueue = newQueue;
}
eventQueue [index] = event;
}
//Display通过调用readAndDispatch方法,后者调用runDeferredEvents方法取出消息队列eventQueue中第一个事件
,并调用事件对应widget的sendEvent方法。
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 invokation
* when running the event.
*/
}
/* Clear the queue */
eventQueue = null;
return run;
}
//widget的sendEvent方法
void sendEvent (Event event) {
Display display = event.display;
if (!display.filterEvent (event)) {
if (eventTable != null) eventTable.sendEvent (event);
}
}
eventTable是widget中保存事件类型和对应监听器的数据结构。eventTable根据event的type找到对应的listener,
然后执行Listener子类TypedListener的handleEvent方法
handleEvent主要的操作就是
SelectionEvent event = new SelectionEvent (e);//对event进一步封装
((SelectionListener) eventListener).widgetSelected (event);//调用对应listener的回调方法。
到此,一个响应用户事件的过程结束。这里只是记录一个过程,以后会就每一点详细讨论。
分享一个源代码学习的网站
http://grepcode.com/file/repository.grepcode.com/java/eclipse.org/4.2/org.eclipse.swt.gtk.linux/x86_64/3.100.0/org/eclipse/swt/widgets/Shell.java#Shell
分享到:
相关推荐
9. 2 触发Servlet链 第10章 服务器端包含 10. 1 服务器端包含的编写 10. 2 服务器端包含的参数传递 10. 3 服务器端包含的实例 第11章 Applet和Servlet通信 11. 1 Applet和Servlet通信概述 11. 2 Applet和...
面向初学Java程序设计的人群,通过AWT完成的一个计算器程序。通过这个程序可以将Java的事件触发过程进行深入的了解。
前 言 致 谢 第一部分 走近Java 第1章 走近Java / 2 1.1 概述 / 2 1.2 Java技术体系 / 3 1.3 Java发展史 / 5 1.4 展望Java技术的未来 / 9 1.4.1 模块化 / 9 1.4.2 混合语言 / 9 1.4.3 多核并行 / 11 ...
Handler使用简单功能强大,常被用作线程间传递消息的组件,而且还可以用于跨进程。 消息机制背后有包括Looper ,MessageQueue管理和分发消息的实现,...这里从Java层开始深入探究下Handler和消息机制背后实现的原理
全书共分为五大部分,围绕内存管理、执行子系统、程序编译与优化、高效并发等核心主题对JVM进行了全面而深入的分析,深刻揭示了JVM的工作原理。第一部分从宏观的角度介绍了整个Java技术体系、Java和JVM的发展历程、...
具体通信流程 1.客户端连接服务端,服务端通过Selector接收到连接请求,将其socketChannel通道保存到通道集合,并触发客户端连接事件 2.客户端发送数据包请求到服务端,服务端将...若要深入了解,请先了解Java NIO技术
javascript中的事件驱动是通过 鼠标或热键 的动作引发的 主要事件如下:1、鼠标单击事件 onclick 如:( <...input type=”text” onchange=”触发的内容” />)通常用于text 文本输入框 –配合onchange,可
Java 虚拟机面试题全面解析,《深入理解Java虚拟机》干货版,自己总结,希望能够帮助大家,免费下载~什么是类加载机制? 虚拟机和物理机的区别是什么? 运行时栈帧结构 Java方法调用 什么是方法调用? Java的方法调用,...
Jib无需Docker守护程序即可为Java应用程序构建优化的Docker和映像-无需深入掌握Docker最佳实践。 它可以作为和插件以及Java库使用。 :请参阅文档 。 :请参阅文档 。 :Java的通用容器构建库。 :使用Jib Core构建...
Jib为您的Java应用程序构建了优化的Docker和OCI映像-无需Docker守护程序或对Docker最佳实践的深入了解。 Jib的构建是通过将传统的单个图像层Java应用程序分成多层,以获得更细致的增量构建。 这样只会导致对要重建...
Spring AOP(面向切面编程)是Java高级编程中的重要组成部分,它允许程序员以声明的方式处理关注点(例如日志、事务管理等),而不是通过硬编码。本文深入分析了Spring AOP的实现机制,让读者能够更好地理解和应用这...
事务的实现原理深入分析Watcher机制的实现原理ClientCnxn 初始化客户端通过 exists 注册监听cnxn.submitRequestSendThread 的发送过程client 和 server 的网络交互服务端接收请求处理流程处理客户端传送过来的数据包...
java简易版开心农场源码 结构说明 设计概要 Meteor-0.8.0的很多东西都是比较新的,对于我来说,是一个比较大的挑战。但是这个新版本同时又是比较诱人的,其中很多功能上的细节让编程变的更加灵活,同时性能上也得到...
Jib无需Docker守护程序即可为Java应用程序构建优化的Docker和映像-无需深入掌握Docker最佳实践。 它可以作为和插件以及Java库使用。 :请参阅有关文档。 :请参阅有关文档。 :Java的通用容器构建库。 :使用Jib ...
本书不仅介绍了基础知识和使用方法,也深入探讨了JavaScript应用示例。 《JavaScript基础教程(第8版)》适合有志于从事Web开发和Web设计的初学者阅读,也是高校相关课程理想的教材。 第1章 了解JavaScript 1 1.1 ...
一、引言 初看责任链模式,心里不禁想起了一个...当一个请求触发后,请求将在这些对象组成的链条中传递,直到找到最合适的“责任”对象,并进行处理。 《设计模式》中给它的定义如下:使多个对象都有机会处理请
由于以前对javascript了解不够深入,一时间手足无措。 后来经过两位高手同事的指点(对这两位同事的...表示该事件的发生源 通俗一点说也就是该事件被触发的地方 3. srcElement[removed]: 表示该事件发生源的父结点 4.
可以基于该应用程序中的事件来触发App Connect流。 介绍 这是在用于与的项目的示例。 此示例使用了一个虚构的Warehouse应用程序,该应用程序连接到IIB,其中IIB将Warehouse应用程序发出的事件详细转换为可以在App ...
第一部分课程从最基础的Android应用开发环境搭建开始,简单讲解了Android界面及事件处理之后,深入剖析Android Handler多线程机制,重点讲解Android NDK应用层与驱动的通信; 第二部分内容,先简单讲解Android系统...
3.7 深入探讨Android活动 3.7.1 创建一个活动 3.7.2 活动生命周期 3.7.3 Android活动类 3.8 小结 第4章 创建用户界面 4.1 Android UI基本设计 4.2 View简介 4.2.1 使用View创建Activity(活动)用户界面 4.2.2 ...