|
发表于 2004-3-6 00:27:46
|
显示全部楼层
在X系统中,由下而上关系是Xlib-->GDK-->GTK。我们先看GDK,大家知道,X和GDK都是一个事件驱动系统,也就是说,它们的工作方式就是从底层系统的事件队列中不停取事件,然后进行相应的处理。当然,这个事件队列是更底层的系统产生的(比如GDK的事件队列是从X中取得,X又从....)。这里,事件是什么?是一种结构,这个结构包括许多要素,比如(鼠标单击,在窗口A上,坐标为X,Y)就是一个事件,可见,事件是自包含的,它含有你所想要的全部信息,根据这些信息,你就可以做许多事。比如,在GDK的基础上你可以设计一个主循环,假设你有两个小部件A,B,你想在当鼠标在A上单击时(一个事件)在B上显示“saga"。你可以这样做你的主循环:1.初始化,做一个表,表中有两项,分别为A,B。A为空,B中放两项clicked-->display表示当B收到clicked时display(显示saga)。2.循环:取事件,若a.单击事件发生的地点在A上(看事件这个结构中的位置项,可以是坐标,也可以是对应的窗口),则A向B发出一个"clicked"(记住这句话),B收到"clicked"就display,b.单击不发生在A上,丢掉这个事件,再取下一个事件进行判断,周而复始。看到吗?假设屏幕上有几十个小部件,每个小部件就如A,B那样做一些表,放入自己收到"clicked"(或其它的什么)时要做的事(一个函数),在主循环中查到(根据位置)在某个小部件上发生"clicked"就查表并做相应的事件(函数),它的功能就如同GTK一样强大了。把这当成一个框架,任何人用它,只要填好那个表,再写好收到"clicked"后要执行的函数就可以了,很方便吧,你都可以做系统架构师了。GTK就是这样做的!(当然GTK还做了太多的其它的事,看它的名字"Gimp ToolKit"--画好小部件是它要做的正事)
将一些词用正式术语替换,这个过程就是这样:主循环收到一个事件(鼠标单击,在窗口A),便由窗口A向B发出一个信号"clicked",B看(在这儿就是查表了)有没有注册了的回调函数(注册--就是那个g_connect_signal的作用了),有一个注册了的函数,就是display(...),便去执行这个函数(在B上显示saga)。
大家看到A是向B发一个信号,其实也可以向自己发一个信号,就是这样描述:当有一个发生在A上的单击事件时,A向A发出一个"clicked"信号,A收到后在A上显示"saga"!而且大多数编程人员的实现中,A就是向自己发一个信号,也就是说,常常是经历了某个事件(A经历了单击这个事件,说经历,是因为发生在自己身上)的小部件发出一个给自己的信号并处理这个信号,有点晕?这正是常常把事件与信号混淆的原因!!!
这样我们就可以总结一些区别了:
1.信号总是由一个小部件发出的。而事件是下层驱动产生的(当然,大多数情况是由人发出再经过系统、X的包装,传到GDK),它自身带有事件产生的位置信息。
2.它们之间有许多相似的函数,比如你可以用gtk_widget_set(add)_events,让一个小部件监听一个事件(比如你可以偷听在不同小部件上发生的鼠标单击),就象听一个信号一样,不同的是你可以听到在其它部件上发生的事件,却不能听到不是发给你的信号。
3.信号有一个传递机制,比如A并没有处理这个信号的回调函数,就会把这个信号向父类传,直到有人处理或到最顶层。而事件始终在事件队列中,你可以向操作系统说(术语就是注册)我关心鼠标单击事件,有了告诉我,你不说,它就不告诉你!
4.还有许多细节上的差异。 |
|