- 1、本文档共8页,可阅读全部内容。
- 2、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。
- 3、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 4、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
GUI 主循环设计及其在 MiniGUI, GTK, QT 的实现
GUI 主循环设计及其在 MiniGUI, GTK, QT 的实现
作者: 刘鹏
日期: 2009-05-22
介绍了 GUI 主循环的设计思路,并分析了 MiniGUI, GTK, QT 的主循环。
简介
我们知道GUI应用程序都是事件驱动的。这些事件大部分都来自于用户,比如键盘事件、鼠标事件或笔点事件。还有一些事件来自于系统内部,比如定时事件、socket事件和其它文件事件等等。在没有任何事件的情况下,应用程序处于睡眠状态。1
因为这种事件驱动机制,GUI应用程序都毫无例外的需要一个主循环(main loop)。 主循环(main loop)控制应用程序什么时候进入睡眠状态,什么时候被唤醒。主 循环实现得好,应用程序才能工作正常又省电。1
目前常见的主循环设计主要是三种思路:
消息队列 + 信号量(semaphore) + sem_wait;
事件源 + select;
事件源 + poll。
对于第一种设计思路,主循环不断的从消息队列中提取消息分发给窗口,如果消息队列中没有消息,主循环调用 sem_wait 进入休眠状态,直到有信息出现被唤 醒。MiniGUI 的主循环就是这样实现的。
对于第二种思路,主循环使用 poll 函数监听事件源,若有事件出现则进行处理, 否则进入休眠状态,直到有事件到来。GTK+ 的主循环就是采用的这种思路。
第三种思路与第二种思路类似,不同之处是主循环使用 select 函数监听事件源, QT 的主循环就是采用的这种思路。
下面结合具体的实现逐一分析这三种思路。
MiniGUI 的主循环
MiniGUI 应用程序的主循环与 Win32 类似,大致如下:
while (GetMessage (Msg, hMainWnd)) {
DispatchMessage (Msg);
}
在 MiniGUI 的主循环中,它不断的从消息队列中提取消息,然后分发给消息的 目标(通常是窗口),直到GetMessage返回FALSE(收到WM_QUIT消息,一般调用 PostQuitMessage)为止,如果队列中没有消息,应用程序就进入睡眠状态。
这种方法的优点是简单明了,但缺陷也是明显的,它只能挂在消息队列上,而不 能同时挂在多个事件源上(如管道和socket等)。要挂在多个事件源上,需要使用 其它方式,比如用WaitForMultipleObjects,那就比较麻烦了。
关于主循环的休眠,MiniGUI 采用的是信号量的方式(sem_wait)。我们进入 GetMessage 接口的实现:
...
checkagain:
LOCK_MSGQ (pMsgQueue);
... peek message ...
UNLOCK_MSGQ (pMsgQueue);
if (bWait) {
/* no message, wait again. */
sem_wait (pMsgQueue-wait);
goto checkagain;
}
GetMessage 调用 sem_wait 函数等待消息队列,若没有消息主循环进入休眠等待状态。
GTK+ 的主循环1
在GTK+应用程序中,其主循环(main loop)更加简单,但是非常的不明了。
每个 gtk 应用程序都有下面这行代码:
gtk_main ();
不少人用GTK+写了很长时间的程序,还是觉得这行代码很神秘,不知道里面到底 干了什么。我们在这里分析下 gtk_main 的工作原理。
gtk_main 主要是对 glib 的 main loop 的包装,基本分为三步:
调用初始化函数;
进入glib main loop;
调用~初始化函数。
所以弄清楚glib main loop之后,gtk_main的实现也就尽收眼底了,这里重点分 析glib的main loop的实现。main loop使用模式大致如下:
loop = g_main_loop_new (NULL, TRUE);
g_main_loop_run (loop);
g_main_loop_quit ();
g_main_loop_new创建一个main loop对象,一个main loop对象只能被一个线程 使用,但一个线程可以有多个main loop对象。在GTK+应用中,一个线程使用多 个main loop的主要用途是实现模态对话框,它在gtk_dialog_run函数里创建一 个新的main loop,通过该main loop分发消息,直到对话框关闭为止。
g_main_loop_run则是进入主循环,它会一直阻塞在这里,直到让它退出为止。 有事件时,它就处理事
文档评论(0)