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

SWT源码分析 (一)

阅读更多

 

阅读本文需要知道搭建swt的开发环境,对SWT有基本的了解,最好对Windows api也有所了解,还要稍微了解一下JNI。

 

 

HelloSWT是一个基本的SWT程序,当点击输入框的时候,会弹出一个MessageBox。

 

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;

class HelloSWT {
public static void main(String[] args) {
Display display = new Display();// 创建一个display对象。
final Shell shell = new Shell(display);// shell是程序的主窗体
shell.setLayout(null); // 设置shell的布局方式
Text hello = new Text(shell, SWT.MULTI); // 声明一个可以显示多行信息的文本框
shell.setText("Java应用程序"); // 设置主窗体的标题
shell.setSize(200, 100); // 设置主窗体的大小
Color color = new Color(Display.getCurrent(), 255, 255, 255);// 声明颜色对象
shell.setBackground(color); // 设置窗体的背景颜色
hello.setText("Hello, SWT World!\n\n你好,SWT世界!");// 设置文本框信息
hello.pack(); // 自动调整文本框的大小
shell.pack(); //自动调整主窗体的大小
shell.open(); // 打开主窗体

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

}
});
while (!shell.isDisposed()) { // 如果主窗体没有关闭则一直循环
if (!display.readAndDispatch()) { // 如果display不忙
display.sleep(); // 休眠
}
}
display.dispose(); // 销毁display
}
}

 

运行效果:

 


这个程序也是我们分析SWT运行的一个介入点。程序中为hello这个Text增加了鼠标事件的监听器,在 MessageBox box = new MessageBox(shell);这一行加上一个断点,因为可以肯定,在点击鼠标时,会执行这段代码,可以通过断点观察出前后程序执行的顺序。当在Text上点击鼠标时,会在断点处暂停,此时运行的上下文为:

 

 

从这里就可以看出程序的执行过程了,先从main方法开始,HelloSWT的51行为 if (!display.readAndDispatch())

 

		while (!shell.isDisposed()) { // 如果主窗体没有关闭则一直循环
			if (!display.readAndDispatch()) { // 如果display不忙
				display.sleep(); // 休眠
			}
		}
		display.dispose(); // 销毁display

 

 readAndDispatch方法在API中的说明为:

 

 

Reads an event from the operating system's event queue, dispatches it appropriately, and returns true if there is potentially more work to do, or false if the caller can sleep until another event is placed on the event queue.

In addition to checking the system event queue, this method also checks if any inter-thread messages (created by syncExec() or asyncExec()) are waiting to be processed, and if so handles them before returning. 

 

从操作系统的事件队列里面读取一个事件,并做适当的分发,返回true时表示有工作要做,返回false表示没有接受到事件。...

当点击鼠标时,程序接收到相应的事件,readAndDispatch()就会返回true。

readAndDispatch的实现为:

 

public boolean readAndDispatch () {
	checkDevice ();
	lpStartupInfo = null;
	drawMenuBars ();
	runSkin ();
	runDeferredLayouts ();
	runPopups ();
	if (OS.PeekMessage (msg, 0, 0, 0, OS.PM_REMOVE)) {
		if (!filterMessage (msg)) {
			OS.TranslateMessage (msg);
			OS.DispatchMessage (msg);
		}
		runDeferredEvents ();
		return true;
	}
	return isDisposed () || (runMessages && runAsyncMessages (false));
}

 

 

方法开始调用了一些其他函数,从名称上来看是做了一些检查和界面显示、菜单的相关操作,我们现在不关心这些,重点看这里:

 

	if (OS.PeekMessage (msg, 0, 0, 0, OS.PM_REMOVE)) {
		if (!filterMessage (msg)) {
			OS.TranslateMessage (msg);
			OS.DispatchMessage (msg);
		}
		runDeferredEvents ();
		return true;
	}

 

 这里出现一个OS类,OS类是SWT内部的一个类,里面定义了很多native方法,我们知道SWT底层通过JNI调用了很多本地的windows api,所以程序的界面和本地的windows程序几乎是一样的,而Swing做出来的界面和具体的平台没关系,和一般的windows程序风格不一样,总是让人感觉不习惯。

OS类如下:

 

public class OS extends C {
	static {
		Library.loadLibrary ("swt"); //$NON-NLS-1$
	}
	......

 

 可见OS类中通过Library.loadLibrary ("swt")加载本地的dll,可以继续进入loafLibrary方法内部,最后得知

加载的是swt-win32-xxxx.dll 。xxxx是eclipse的版本号。在我的机器上是swt-win32-3650.dll。这个dll在eclipse安装目录下的plugins目录中的org.eclipse.swt.win32.win32.x86_3.6.0.v3650b.jar中。还有一个org.eclipse.swt.win32.win32.x86.source_3.6.0.v3650b.jar,里面是swt的源码。解压这个源码的jar之后,可以看到一个os.c文件,我猜测,OS类的native方法的实现就是在os.c中,并没有去验证。

os.c 的部分代码:

 

#include "swt.h"
#include "os_structs.h"
#include "os_stats.h"

#define OS_NATIVE(func) Java_org_eclipse_swt_internal_win32_OS_##func

......

#ifndef NO_PeekMessageA
JNIEXPORT jboolean JNICALL OS_NATIVE(PeekMessageA)
	(JNIEnv *env, jclass that, jobject arg0, jintLong arg1, jint arg2, jint arg3, jint arg4)
{
	MSG _arg0, *lparg0=NULL;
	jboolean rc = 0;
	OS_NATIVE_ENTER(env, that, PeekMessageA_FUNC);
	if (arg0) if ((lparg0 = getMSGFields(env, arg0, &_arg0)) == NULL) goto fail;
	rc = (jboolean)PeekMessageA(lparg0, (HWND)arg1, arg2, arg3, arg4);
fail:
	if (arg0 && lparg0) setMSGFields(env, arg0, lparg0);
	OS_NATIVE_EXIT(env, that, PeekMessageA_FUNC);
	return rc;
}
#endif

 

不同函数的定义都是类似:

 JNIEXPORT jboolean JNICALL OS_NATIVE(PeekMessageA)

(JNIEnv *env, jclass that, jobject arg0, jintLong arg1, jint arg2, jint arg3, jint arg4)

 

其中OS_NATIVE是一个宏,以上函数实际的定义为:

 

JNIEXPORT jboolean JNICALL Java_org_eclipse_swt_internal_win32_OS_PeekMessageA

(JNIEnv *env, jclass that, jobject arg0, jintLong arg1, jint arg2, jint arg3, jint arg4)

 

 

函数名为 :java中的包名_类名_方法名。这种格式是JNI要求的。

 

现在知道了,SWT调用OS类的static native方法就相当于直接调用了Windows SDK Api。

回到Display类中,OS.PeekMessage的作用是从系统的消息队列取消息,如果取到了消息就返回true。

 

OS.TranslateMessage (msg);将消息进行一些转化。

OS.DispatchMessage (msg);将消息发送给相应的窗口。

 

这几个都是windows api 函数,不清楚也不要紧,这些是每个windows程序都有的,后面我会贴出一个最简单的

windows c程序。

 

随后是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;
}

 作用是从SWT的 eventQuene中取出一个事件(事件是怎么放入到eventQueue中的呢?后面说),找到事件对应的控件,让这个控件去处理这个事件。

 

到现在分析到前面断点那个图的第三步,后面的过程会继续分析。

未完待续。

  • 大小: 16.4 KB
  • 大小: 5.8 KB
3
0
分享到:
评论
1 楼 xiaguangme 2013-03-06  
写的不错,赞一个

相关推荐

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

     Java实现HTTP连接与浏览,Java源码下载,输入html文件地址或网址,显示页面和HTML源文件,一步步的实现过程请下载本实例的Java源码,代码中包括丰富的注释,对学习有帮助。 Java实现的FTP连接与数据浏览程序 1个...

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

     Java实现HTTP连接与浏览,Java源码下载,输入html文件地址或网址,显示页面和HTML源文件,一步步的实现过程请下载本实例的Java源码,代码中包括丰富的注释,对学习有帮助。 Java实现的FTP连接与数据浏览程序 1个...

    Eclipse从入门到精通 陈刚 源码

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

    java源码包2

     Java实现HTTP连接与浏览,Java源码下载,输入html文件地址或网址,显示页面和HTML源文件,一步步的实现过程请下载本实例的Java源码,代码中包括丰富的注释,对学习有帮助。 Java实现的FTP连接与数据浏览程序 1个...

    java源码包3

     Java实现HTTP连接与浏览,Java源码下载,输入html文件地址或网址,显示页面和HTML源文件,一步步的实现过程请下载本实例的Java源码,代码中包括丰富的注释,对学习有帮助。 Java实现的FTP连接与数据浏览程序 1个...

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

     Java实现HTTP连接与浏览,Java源码下载,输入html文件地址或网址,显示页面和HTML源文件,一步步的实现过程请下载本实例的Java源码,代码中包括丰富的注释,对学习有帮助。 Java实现的FTP连接与数据浏览程序 1个...

    java源码包4

     Java实现HTTP连接与浏览,Java源码下载,输入html文件地址或网址,显示页面和HTML源文件,一步步的实现过程请下载本实例的Java源码,代码中包括丰富的注释,对学习有帮助。 Java实现的FTP连接与数据浏览程序 1个...

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

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

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

    Java目录监视器源程序 9个目标文件 内容索引:JAVA源码,综合应用,目录监视 用JAVA开发的一个小型的目录监视系统,系统会每5秒自动扫描一次需要监视的目录,可以用来监视目录中文件大小及文件增减数目的变化。...

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

    Java目录监视器源程序 9个目标文件 内容索引:JAVA源码,综合应用,目录监视 用JAVA开发的一个小型的目录监视系统,系统会每5秒自动扫描一次需要监视的目录,可以用来监视目录中文件大小及文件增减数目的变化。...

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

    这个例子用于分析了一些以逗号为分割符的文本文件,例如在你的\MSDEV\LIB(VC5.0在DevStudio\VC\Lib)目录下的Win32Api.CSV就是这样的文件(16KB)<END><br>53,scrl.zip 这是一个由Visual C++ 5.0开发的基于对话框的...

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

    第一部分 开发入门 第1章 Eclipse概述及开发环境搭建 2 1.1 Eclipse概述 2 1.1.1 Eclipse的由来和发展 2 1.1.2 Eclipse的结构和平台内核 2 1.2 Eclipse开发环境的搭建 3 1.2.1 JDK的安装 4 1.2.2 JDK...

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

    2.3.3 开发Java第一个程序21 2.3.4 Java代码中的注释23 2.3.5 常见错误解析24 2.4 Java类库组织结构和文档27 2.5 Java虚拟机简介28 2.6 Java技术两种核心运行机制29 2.7 上机练习30 第3章 3.1 变量32 3.1.1 什么是...

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

    1.3 第一个Java 实例... 4 1.3.1 新建Java 项目... 4 1.3.2 配置构建路径... 4 1.3.3 新建Java 类... 5 1.3.4 设置命令行参数... 5 1.3.5 运行实例... 6 1.4 Java 应用程序实例... 6 1.4.1 排序算法的...

Global site tag (gtag.js) - Google Analytics