打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

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

一、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事件的操作。
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
GTK学习[一]:GTK中的信号(Signal)与事件
Gtk+/Cairo/Glitz
学习使用GTK+ 3.使用GtkBuilder、界面设计器Glade和其他GTK+组件 | f(Program,Poet)=Programet
g_signal_connect 与 g_signal_connect_swapped
线程中CreateEvent和SetEvent及WaitForSingleObject的用...
WaitForSingleObject的用法--小浪的博客
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服