`

深入JAVA事件触发

 
阅读更多
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
分享到:
评论

相关推荐

    深入Java Servlet网络编程

    9. 2 触发Servlet链 第10章 服务器端包含 10. 1 服务器端包含的编写 10. 2 服务器端包含的参数传递 10. 3 服务器端包含的实例 第11章 Applet和Servlet通信 11. 1 Applet和Servlet通信概述 11. 2 Applet和...

    计算器--Java程序

    面向初学Java程序设计的人群,通过AWT完成的一个计算器程序。通过这个程序可以将Java的事件触发过程进行深入的了解。

    深入理解_Java_虚拟机 JVM_高级特性与最佳实践

    前 言 致 谢 第一部分 走近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机制及原理探究.pdf

    Handler使用简单功能强大,常被用作线程间传递消息的组件,而且还可以用于跨进程。 消息机制背后有包括Looper ,MessageQueue管理和分发消息的实现,...这里从Java层开始深入探究下Handler和消息机制背后实现的原理

    Java虚拟机

    全书共分为五大部分,围绕内存管理、执行子系统、程序编译与优化、高效并发等核心主题对JVM进行了全面而深入的分析,深刻揭示了JVM的工作原理。第一部分从宏观的角度介绍了整个Java技术体系、Java和JVM的发展历程、...

    封装一套简单易于使用的流式异步通信框架,追求易于理解,方便使用.rar

    具体通信流程 1.客户端连接服务端,服务端通过Selector接收到连接请求,将其socketChannel通道保存到通道集合,并触发客户端连接事件 2.客户端发送数据包请求到服务端,服务端将...若要深入了解,请先了解Java NIO技术

    深入理解javaScript中的事件驱动

    javascript中的事件驱动是通过 鼠标或热键 的动作引发的 主要事件如下:1、鼠标单击事件 onclick 如:( &lt;...input type=”text” onchange=”触发的内容” /&gt;)通常用于text 文本输入框 –配合onchange,可

    Java 虚拟机面试题全面解析(干货)

    Java 虚拟机面试题全面解析,《深入理解Java虚拟机》干货版,自己总结,希望能够帮助大家,免费下载~什么是类加载机制? 虚拟机和物理机的区别是什么? 运行时栈帧结构 Java方法调用 什么是方法调用? Java的方法调用,...

    臂架::building_construction:为Java应用程序构建容器映像

    Jib无需Docker守护程序即可为Java应用程序构建优化的Docker和映像-无需深入掌握Docker最佳实践。 它可以作为和插件以及Java库使用。 :请参阅文档 。 :请参阅文档 。 :Java的通用容器构建库。 :使用Jib Core构建...

    Jib:容器化您的Java应用程序-开源

    Jib为您的Java应用程序构建了优化的Docker和OCI映像-无需Docker守护程序或对Docker最佳实践的深入了解。 Jib的构建是通过将传统的单个图像层Java应用程序分成多层,以获得更细致的增量构建。 这样只会导致对要重建...

    Spring AOP源码深度解析:掌握Java高级编程核心技术

    Spring AOP(面向切面编程)是Java高级编程中的重要组成部分,它允许程序员以声明的方式处理关注点(例如日志、事务管理等),而不是通过硬编码。本文深入分析了Spring AOP的实现机制,让读者能够更好地理解和应用这...

    分布式专题-04分布式协调服务之Zookeeper实践及与原理分析

    事务的实现原理深入分析Watcher机制的实现原理ClientCnxn 初始化客户端通过 exists 注册监听cnxn.submitRequestSendThread 的发送过程client 和 server 的网络交互服务端接收请求处理流程处理客户端传送过来的数据包...

    java简易版开心农场源码-DE-Grid:德格

    java简易版开心农场源码 结构说明 设计概要 Meteor-0.8.0的很多东西都是比较新的,对于我来说,是一个比较大的挑战。但是这个新版本同时又是比较诱人的,其中很多功能上的细节让编程变的更加灵活,同时性能上也得到...

    jib::building_construction:为Java应用程序构建容器映像

    Jib无需Docker守护程序即可为Java应用程序构建优化的Docker和映像-无需深入掌握Docker最佳实践。 它可以作为和插件以及Java库使用。 :请参阅有关文档。 :请参阅有关文档。 :Java的通用容器构建库。 :使用Jib ...

    JavaScript基础教程第8版

    本书不仅介绍了基础知识和使用方法,也深入探讨了JavaScript应用示例。 《JavaScript基础教程(第8版)》适合有志于从事Web开发和Web设计的初学者阅读,也是高校相关课程理想的教材。 第1章 了解JavaScript 1 1.1 ...

    嵌入式系统/ARM技术中的深入浅出:什么是基于Java的责任链模式

    一、引言  初看责任链模式,心里不禁想起了一个...当一个请求触发后,请求将在这些对象组成的链条中传递,直到找到最合适的“责任”对象,并进行处理。  《设计模式》中给它的定义如下:使多个对象都有机会处理请

    javascript结合Cookies实现浏览记录历史第1/3页

    由于以前对javascript了解不够深入,一时间手足无措。 后来经过两位高手同事的指点(对这两位同事的...表示该事件的发生源 通俗一点说也就是该事件被触发的地方 3. srcElement[removed]: 表示该事件发生源的父结点 4.

    iib-app-connect-trigger-pattern:来自IBM Integration Bus的发布事件的一种模式,将用作IBM App Connect的触发器

    可以基于该应用程序中的事件来触发App Connect流。 介绍 这是在用于与的项目的示例。 此示例使用了一个虚构的Warehouse应用程序,该应用程序连接到IIB,其中IIB将Warehouse应用程序发出的事件详细转换为可以在App ...

    ARM Cortex-A8和Android 4.x联动报警系统

    第一部分课程从最基础的Android应用开发环境搭建开始,简单讲解了Android界面及事件处理之后,深入剖析Android Handler多线程机制,重点讲解Android NDK应用层与驱动的通信; 第二部分内容,先简单讲解Android系统...

    Android高级编程.pdf

    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 ...

Global site tag (gtag.js) - Google Analytics