`

深入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 触发事件应用实例

    Java触发事件应用实例是Java编程中的重要组成部分,主要用于构建用户交互性强的应用程序。在Java中,事件处理主要是通过事件监听器、事件源和事件对象来实现的。本篇将深入探讨Java事件处理机制,以及如何在实际应用...

    java事件 按钮单击事件 实例

    本实例将深入探讨Java事件处理机制,特别是按钮的单击事件。在Java Swing或JavaFX库中,我们可以创建按钮并定义其单击行为。以下是关于这个主题的详细讲解。 首先,我们需要导入必要的Java Swing库,如`javax.swing...

    JAVA事件处理机制

    下面我们将深入探讨这些组件以及相关的事件监听器适配器。 首先,事件源是产生事件的对象,通常是UI组件,如按钮、文本框等。当用户与这些组件交互时,事件源会生成相应的事件。例如,当用户点击一个按钮时,按钮...

    JAVA事件处理指南

    在这种模式下,事件源(通常是GUI组件,如按钮、文本框等)是被观察的对象,当它们的状态发生改变时,会触发事件。而事件监听器则是观察者,注册到事件源上,接收并处理这些事件。 Java AWT和Swing库提供了丰富的...

    java事件 鼠标事件 实例代码

    在这个特定的主题中,我们关注的是"Java事件",特别是"鼠标事件",并通过实例代码来深入理解这一概念。 Java事件模型基于观察者模式,其中事件源(通常是组件如按钮或文本框)生成事件,而事件监听器则注册以接收...

    用Java事件处理机制实现录制回放功能

    在本文中,我们将深入探讨如何利用Java事件处理机制实现录制和回放功能,这种功能常见于GUI测试工具中,用于捕获用户操作并在代码修改后自动回放这些操作。 1. Java 事件介绍 - **事件是什么**:在Java中,事件是...

    java事件 键盘事件 实例代码

    本篇将深入探讨Java中的键盘事件,并提供一个名为`KeyEventDemo1.java`的实例代码。 首先,我们要理解Java AWT(Abstract Window Toolkit)和Swing库是如何处理键盘事件的。这两个库提供了图形用户界面组件,如按钮...

    java事件处理编程范例

    当事件发生时,事件源会触发事件,并通知已注册的监听器。Java Swing和JavaFX提供了丰富的组件库,这些组件都可以生成各种类型的事件。 在Java中,有两种主要的事件监听接口:EventListener和ActionListener。Event...

    java事件处理机制Demo

    本示例"java事件处理机制Demo"将深入探讨Java的观察者模式(Observer Pattern)及其在实际项目中的应用。 首先,我们来理解什么是观察者模式。观察者模式是一种行为设计模式,它定义了对象之间的一对多依赖关系,当...

    深入浅出学习Java事件处理

    ### 深入浅出学习Java事件处理 #### 一、Java事件处理概述 Java图形用户界面(GUI)的设计依赖于强大的事件处理机制来响应用户的输入操作和其他动态变化。事件处理是实现用户与程序交互的核心技术之一。在Java中,...

    事件驱动模型实例详解(Java篇)

    而事件处理程序则具体执行事件触发后的逻辑。 #### 2. 生活中的事件驱动模型示例 想象一下,你在街头行走时不幸被高空坠落的花瓶砸中,随后失去意识。这一系列事件其实遵循着事件驱动模型的框架: 1. **事件源**...

    java事件例子

    Java事件模型主要基于观察者模式,其中事件源(通常是组件,如按钮、文本框等)是被观察的对象,而事件监听器则是观察者,负责处理由事件源触发的事件。Java AWT和Swing库提供了丰富的组件和事件类来支持这一机制。 ...

    初步接触Java事件机制

    事件源是触发事件的对象,通常是UI组件,如按钮、文本框等。在Java中,所有可以生成事件的组件都实现了EventListener接口,或者包含了一个或多个事件监听器的注册方法。 3. **事件监听器** (Event Listener): ...

    JAVA基础:深入浅析java语言的事件处理

    这段代码中,`Exam`类提供了一个`addListener`方法用于注册监听器,并且在属性发生变化时通过`firePropertyChange`方法触发事件。 ##### 4. 触发事件 当事件源的状态发生变化时,需要通过调用`firePropertyChange`...

    java自定义事件监听

    在Java编程语言中,事件监听是构建用户界面(UI)应用程序的一个关键概念。...Java自定义事件监听允许开发者创建自己的事件类型并相应...对于希望深入理解Java GUI编程的开发者来说,掌握自定义事件监听是必不可少的技能。

    Java 开发中事件驱动模型的实例详解

    在Java开发领域,事件驱动模型(Event-Driven Model)是一种广泛采用的设计模式,它通过响应外部事件来触发程序中的特定行为。本文将深入探讨Java中事件驱动模型的应用,特别是通过Swing框架的具体实例来解析这一...

    java事件单击事件 实例代码

    在这个实例中,我们将深入探讨Java中的事件单击事件,特别是关于"LookAndFeelDemo.java"文件的代码。 Java AWT(Abstract Window Toolkit)和Swing库都包含了处理事件的机制。在Swing中,事件通常通过监听器...

    java JComboBox的事件处理

    本篇文章将深入探讨Java中JComboBox的事件处理机制,以及如何通过编程实现这些功能。 JComboBox的事件主要分为两类:ActionEvent和ItemEvent。ActionEvent通常发生在用户从下拉列表中选择一个选项并点击确认按钮...

    java鼠标事件使用的简单例子

    本篇文章将深入探讨如何在Java中实现鼠标事件监听,包括点击、移动和释放等行为,并通过一个简单的例子来说明。 首先,我们需要了解Java AWT(Abstract Window Toolkit)和Swing库提供的鼠标事件类和监听器接口。...

Global site tag (gtag.js) - Google Analytics