GTK+中文社区(gtk.awaysoft.com)

 找回密码
 马上加入

QQ登录

只需一步,快速开始

查看: 4317|回复: 0

【转】关于GTK各个循环函数的介绍与使用

[复制链接]
  • TA的每日心情
    奋斗
    2021-11-19 13:15
  • 签到天数: 20 天

    连续签到: 1 天

    [LV.4]偶尔看看III

    发表于 2009-4-25 15:50:46 | 显示全部楼层 |阅读模式
    文章原地址:[url:30ngzi17]http://blog.csdn.net/freelyc/archive/2008/12/18/3547855.aspx[/url:30ngzi17]
    Gtk+主循环的首要目的就是在连接到X服务器的文件描述符上监听事件,并将事件转发到构件上。本节解释怎样使用主循环,怎样给主循环添加新功能:当主循环在指定的时间间隔内空闲时、当一个文件描述符已经读或写就绪、以及当主循环退出时调用一个函数。
    2.10.1主循环基本知识
    从根本上来说,主循环是由glib实现的。Gtk+将glib主循环连接到Gdk的X服务器,并提供一个方便的接口(glib循环是比Gtk+的循环更低层的)。
    gtk_main()函数运行主循环。直到调用gtk_main_quit()函数,gtk_main()才会退出。gtk_main()函数可以递归调用,每次调用一个gtk_main_quit()就退出gtk_main()函数的一个实例。gtk_main_level()函数返回递归的层次,也就是:如果没有gtk_main()运行,返回0;如果一个gtk_main()函数在运行,返回1,等等。
    gtk_main()函数的所有实例功能都是一样的,它们都监视同一个与X服务器的连接,都对同样的事件队列起作用。gtk_main()实例用于阻塞、遮断一个函数的控制流直到满足某些条件。
    所有的Gtk+程序都用这个技巧使应用程序正在运行时main()函数不能退出去。gnome_dialog_run()函数使用了一个递归的主循环,此循环直到用户点击对话框的按钮时它才会返回。
    有时候想处理一些事件,又不想将控制交给gtk_main(),可以调用gtk_main_iteration()函数对主循环进行迭代。例如,这样可以处理单独的一个事件,它依赖于想将什么任务挂起。可以检查是否有任何事件需要通过调用gtk_events_pending()函数处理。同样地,这两个函数允许临时将控制交还给Gtk+。例如,在一个很长的计算中,想显示一个进度条,必须允许Gtk+主循环周期性地返回,让Gtk+能重画进度条。可以使用下面的代码:
    while(gtk_events_pending())
    gtk_main_iteration();
    下面是有关主循环的函数:
    #include<gtk/gtkmain.h>
    voidgtk_main()
    voidgtk_main_quit()
    voidgtk_main_iteration()
    gintgtk_events_pending()
    guintgtk_main_level()
    2.10.2退出函数
    退出函数就是当调用gtk_main_quit()函数时要调用的回调函数。换句话说,回调函数只在 gtk_main()返回之前运行。回调函数应该是一个像下面这样定义的GtkFunction:
    typedefgint(*GtkFunction)(gpointerdata);
    退出函数是用gtk_quit_add()添加进去的。添加退出函数时,必须指定一个由gtk_main_level()返回的主循环的级别。第二个和第三个参数指定一个回调函数和回调数据。回调函数的返回值说明了回调函数是否应该再次调用。只要回调函数返回TRUE,它会被重复调用。只要它返回 FALSE,将取消与主循环的连接,并且不会再次调用。所有的退出函数都返回FALSE时,gtk_main()会返回。
    gtk_quit_add()函数返回一个ID号码,可以用于用gtk_quit_remove()函数删除该退出函数。还可以通过将回调数据传递给gtk_quit_remove_by_data()函数来删除退出函数。函数列表:退出函数
    #include<gtk/gtkmain.h>
    guintgtk_quit_add(guintmain_level,
    GtkFunctionfunction,
    gpointerdata)
    voidgtk_quit_remove(guintquit_handler_id)
    voidgtk_quit_remove_by_data(gpointerdata)
    2.10.3Timeout函数
    有时候可能想应该在gtk_main主循环中怎样让GTK做点什么。这时可以创建一个定时(Timeout)函数,隔一定时间(毫秒)就调用一次。Timeout类似于其他编程环境中的定时器控件。下面的函数用于添加一
    Timeout函数。
    #include<gtk/gtkmain.h>
    gintgtk_timeout_add(guint32interval,
    GtkFunctionfunction,
    gpointerdata);
    第一个参数调用定时函数的时间间隔,以毫秒计。第二个参数是要调用的函数,第三个是要传递给函数的参数。函数返回一个整数值“标志”。可以用下面的函数停止调用定时函数:
    #include<gtk/gtkmain.h>
    voidgtk_timeout_remove(ginttag);
    其中tag参数是前一个函数返回的“标志”值。还可以让回调函数返回FALSE或0来停止调用定时函数。也就是说,要想让函数继续调用,必须让它返回一个非0值或TRUE。定期调用的回调函数声明应该是下面的形式:
    ginttimeout_callback(gpointerdata);
    可以看到,Timeout函数类似于许多可视化编程工具中的Timer控件(计时器)。
    2.10.4idle函数
    当Gtk+主循环没有其他事情做时,idle函数连续运行。只有在事件队列是空的,并且主循环正常空闲着,正等待着有什么事情发生时,idle函数才会运行。只要它们返回TRUE,这个函数就会一次又一次地调用;当它们返回FALSE时,函数会被删除,就像调用了gtk_idle_remove() 函数一样。
    列在下面函数列表中的idle函数API,与timeout以及退出函数API是一样的。不过,不能在idle函数中调用 gtk_idle_remove()函数,因为它会破坏Gtk+的函数列表。要返回FALSE来删除idle函数。idle函数在对“只此一次”的代码排队时通常是很有用的,这样的代码一般在所有的事件已经处理之后才运行。相对昂贵(耗费系统资源较多)的操作,比如Gtk+的大小协商以及 GnomeCanvas重绘一般在返回FALSE的idle函数中发生。这保证了代价昂贵的操作只会执行一次,即使多个连续的事件独立地要求重新执行。
    Gtk+的主循环包含一个简单的调度程序。idle函数有一个分配给它们的优先级,就像UNIX进程所做的一样,也可以分配一个非缺省的优先级给idle函数。
    函数列表:idle函数
    #include<gtk/gtkmain.h>
    guintgtk_idle_add(GtkFunctionfunction,
    gpointerdata)
    voidgtk_idle_remove(guintidle_handler_id)
    voidgtk_idle_remove_by_data(gpointerdata)
    2.10.5输入函数
    输入函数用于检查文件描述符的数据(由open(2)或socket(2)返回的文件描述符)。输入函数是在Gdk级处理的。当给定的文件描述符已经读写就绪时,会调用输入函数。它们对网络应用程序特别有用。关于文件描述符请参考Unix编程方面的参考书。要添加一个输入函数,需要指定要监视的文件描述符、要等待的状态(读或写就绪),以及一个回调函数/数据对。下面的函数列表列出了这些API。该函数可以用gdk_input_add()返回
    的标识符删除。不像quit、timeout和idle函数,从输入函数里面调用gdk_input_remove()函数删除该函数是安全的,Gtk+不会处于输入函数列表的迭代状态。
    要指定等待的条件,使用GdkInputCondition标志:
    GDK_INPUT_READ
    GDK_INPUT_WRITE
    GDK_INPUT_EXCEPTION
    可以用OR将一个以上的标志连在一起。这些标志对应于传到select()系统调用的三种文件描述符集。要了解详细的内容,请参考UNIX的编程参考书。如果所有条件都得到满足,就会调用输入函数。
    回调函数应该是这个样子:
    typedefvoid(*GdkInputFunction)(gpointerdata,
    gintsource_fd,
    GdkInputConditioncondition);
    它接受回调数据、被监视的文件描述符以及要满足的条件(可能是一个正在监视的条件的子集)。函数列表:输入函数
    #include<gdk/gdk.h>
    gintgdk_input_add(gintsource_fd,
    GdkInputConditioncondition,
    GdkInputFunctionfunction,
    gpointerdata)
    voidgdk_input_remove(ginttag)
    2.11编译应用程序
    用前面所介绍的基本概念,已经可以编译全功能的Gtk+/Gnome应用程序了。但是还有一个大问题:如何配置编译选项?一些实用工具如automake、autoconf、libtool等,可以用来简化这一过程。
    为了方便维护,同时,也是为了便于使用这些实用工具,应该在编写代码时遵从一些约定。如果要将程序发布为自由软件,最好能使程序源代码的目录结构遵从 “GNU项目编码标准”。即使应用程序是私有的商用程序,不想公开源代码,从技术上来说,这么做也是一个非常好的选择,因为这些标准都是经过实践检验,能够让你节省大量的时间和精力。另外还应该在程序代码中包含INSTALL、README的文件。
    *滑块验证:
    您需要登录后才可以回帖 登录 | 马上加入

    本版积分规则

    申请友链|Archiver|小黑屋|手机版|GTK+中文社区 ( 粤ICP备13080851号 )

    我要啦免费统计

    GMT+8, 2024-4-28 11:25 , Processed in 0.130749 second(s), 7 queries , Redis On.

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表