Chinaunix首页 | 论坛 | 博客
  • 博客访问: 351701
  • 博文数量: 82
  • 博客积分: 3353
  • 博客等级: 中校
  • 技术积分: 742
  • 用 户 组: 普通用户
  • 注册时间: 2008-11-20 19:13
文章分类

全部博文(82)

文章存档

2015年(1)

2014年(1)

2013年(1)

2012年(12)

2011年(3)

2010年(25)

2009年(37)

2008年(2)

我的朋友

分类: LINUX

2010-07-01 10:57:04

Gtk事件与信号关系

--分析中相关的源码包 gtk+2.0-2.12.9
  
   Gtk所提供的工具库与Gtk应用程序与都是基于事件触发机制来管理。所有的Gtk应用程序都是基于事件驱动,如果没有事件发生,应用程序将处于等待状 态,不会执行任何操作,一旦事件发生,将根据不同的事件做出相应的处理。在GTK+中,一个事件就是从X Server传出来的一个信息。当一个事件发生时,Gtk程序就会通过发送一个信号来通知应用程序执行相关的操作,即调用指定控件与这一信号进行绑定的回 调函数,来完成一次由事件所触发的行动。

一、通过对源代码分析,解决理解过程中所产生的问题:
 
    1、Gtk应用程序如何能接收到来至XServer端的事件:
  
          根据以前的分析可知,GDK层所提供的事件循环对XServer端传过来的事件进行管理,并将其转化为GDK层的事件,通过对具体源代码的分析,可以知道Gtk应用程序能接收的事件,便是来自GDK层进行加工过的Gdk事件。
  
          在程序中可以得知,当有事件需要处理时,Gdk层对XServer端的事件以队列的形式进行管理(_gdk_events_queue),并将X事件通过 (gdk_event_translate)转换为GDK事件,将转换后的事件放入队列中,每次从队列中取出队首的事件 (_gdk_event_unqueue),如果事件不为空,这时程序中的处理是将GDK事件GdkEvent交给了_gdk_event_func函数 进行处理,到这我们可以知道,由XServer端产生的事件经过GDK层后将事件由一个函数_gdk_event_func来处理。

          进一步分析知道,_gdk_event_func这一函数指针做为一个GDK提供给外部的一个接口,外部程序如果实现这一接口,便可以接收来自GDK层转 换XServer端产生的事件,在对Gtk的分析过程中,该接口是由Gtk来实现(gtk_main_do_event),也就是Gtk程序通过这一函数 来处理事件。

          当程序在调用gtk_init时对_gdk_event_func进行设置。

    2、Gtk应用程序接收到事件后如何对事件进行处理:
  
          在进一步的分析中,Gtk应用程序采用了信号的机制,通过信号的方式,通知Gtk其它的控件做出相应的动作。每一个控件都有自己定义的信号,每一个信号都可以绑定到一个指定的回调函数上。
         
          从gtk_main_do_event函数中,通过调用内部函数(如:gtk_widget_event_internal)将GDK事件关联到Gtk自 身定义的信号上,并将信号发出,绑定这一信号的控件便可以接收到,这样根据信号的定义执行相应的回调函数。

二、以对GtkButton控件的点击事件(press-release-click)为例,进行分析:
    
         当鼠标点击在GtkButton上时,系统做出了以下的反应:
   
         由于XServer实时接收着来至输入设备的操作,当鼠标点击后,XServer立即生成一个XEvent结构,里面描述着所点击的控件,XEvent产 生的事件类型等具体信息,这时将这一事件传给GDK层,GDK层通过将XEvent事件转化为GdkEvent,将转化后的事件交给函数接口 (_gdk_event_func)处理,即gtk_main_do_event。经过几层函数调用的处理,在函数gtk_widget_event中调 用gtk_widget_event_internal,将事件转化成为Gtk中的信号类型,并通过g_signal_emit将GtkButton的信 号BUTTON_PRESS_EVENT发送出去。
  
         在gtkwindow.c文件中,对GtkWidgetClass创建了BUTTON_PRESS_EVENT、 BUTTON_RELEASE_EVENT等类型信号,BUTTON_PRESS_EVENT与 函数button_press_event关联,GtkButton类型继承了父类GtkWidget的信号,并将函数 button_press_event进行重载为gtk_button_button_press。在GtkButton结构中定义自己的信 号"PRESSED",关联函数为gtk_real_button_pressed。

         在GtkButton中定义了与单击按钮时关联的信号类型为: PRESSED,RELEASED,CLICKED。

         通过分析源码,信号的流程是在gtk_widget_event_internal函数中所发出的信号由GtkWidget所接收(所有widget的父 类,如GtkButton), 再由GtkWidget中对这一信号所关联的回调函数(gtk_button_button_press),来发出由GtkWidget子类所定义的信 号,最终的操作在于GtkWidget子类中信号的定义。即最终信号的发出是gtk_button_pressed调用g_signal_emit将 “PRESSED”信号发出,调用回调函数gtk_real_button_pressed修改GtkButton的属性。

         以同样的方式,处理鼠标对按钮的释放(release)事件,当RELEASED信号发出后,调用与RELEASED信号相关联的回调函数,根据当前 GtkButton的属性进行判断如果当前按钮满足一定的条件,如当前按钮是否处于按下(down)状态等,则由gtk_button_clicked, 发出一个"CLICKED"信号,调用与"CLICKED"关联的回调函数执行click事件的操作。

三、参考资料

   http://library.gnome.org/devel/gtk-tutorial/stable/
   No.Starch.Press.The.Official.GNOME.2.Developers.Guide.eBook-LiB.pdf
阅读(2398) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~