GTK之信号和回调函数

  在 2.0 版,信号系统已从 GTK 移到 GLib,因此在函数和类型的说明中有前缀 “g_” 而不是 “gtk_”。
  GTK 是一个事件驱动的工具包,意味着它会等在gtk_main() 那里, 直到下一个事件发生, 才把控制权传给适当 的函数。控制权的传递是使用“信号”的办法来完成的。(注意这里的信号并不等同于Unix 系统里的信号,并且也不是用它们实现的,虽然使用的术语是一样的。)

1.常用信号

  构件能够发送各种信号,信号可以由用户操作而引起,也可以由函数模拟事件产生,常见信号如下。

构件 信号 意义 产生信号函数
windows “destroy” 关闭窗口时发出该信号
button “clicked” 点击按钮,这是按下和释放操作的组合 gtk_button_clicked(button)
“enter” 鼠标移到按钮之上 gtk_button_enter(button)
“leave” 鼠标离开按钮 gtk_button_leave(button)
“pressed” 按下按钮 gtk_button_pressed(button)
“released” 释放按钮 gtk_button_released(button)
toggle_button “toggled” 开关按钮
listbox “select” 列表框被选择
“selection_changed” 列表框选择被更改
GTKRadioMenuItem “activate” 菜单选项被选择

  GTK+的两个基本机制是delete_event事件和destroy信号,当将要关闭窗口时,出现delete_event事件。当关闭窗口时,发出destroy信号。对于delete_event事件,顶层窗口应该设有相应的回呼函数。因为delete_event表示用户需要关闭应用软件。对于delete_event信号增加回呼函数包括两个步骤。
  delete_event的回呼函数应该返回布尔值,用以表示是否允许关闭窗口。返回TRUR值保持窗口打开,返回FALSE值表示窗口可以关闭。如果关闭窗口,接着发出destroy信号告诉应用程序就要关闭窗口。

2.信号连接和处理函数

2.1 信号连接函数 g_signal_connect

 /* 信号连接函数*/
#define g_signal_connect(instance, detailed_signal, c_handler, data)
形参:instance  --void*指针,要发出信号的构件
detailed_signal  -- char *指针,连接的信号的名称c_handler  --信号被捕获时所要调用的函数data   -- void*指针,传递给信号处理函数(回调函数)的数据
返回值:gulong类型,返回识别回调函数的标识
第三个参数即回调函数一般形式如下:
void callback_func( GtkWidget *widget,gpointer callback_data );
形参:widget -- 指向发出信号的构件的指针callback_data  --g_signal_connect传入的参数
注意:上面回调函数的声明只是一般的形式, 有些构件的特殊信号会用不同的调用参数。

  每个信号和每个对象可以有多个回调函数,并且它们会按设置的顺序依次运行。

2.2 g_signal_connect返回值

  信号连接函数g_signal_connect返回值为glong类型,返回一个识别回调函数的标志。因为每个信号和每个对象可以有多个回调函数,并且它们会按设置的顺序依次运行。所以可以通过这个返回标志,可通过下面函数将实现的回调函数删除:

g_signal_handler_disconnect(gpointer instance, gulong handler_id)

  所以,通过传递你想在上面删除处理函数的构件,以及某个signal_connect函数返回的标识,你就可以中断一个信号处理函数的连接。
  也可以使用g_signal_handler_block() 和 g_signal_handler_unblock() 这类函数来暂时断开信号处理函数的连接。

void g_signal_handler_block (gpointer instance, gulong handler_id);
void g_signal_handlers_block_by_func( gpointer object,GCallback func,gpointer data );
void g_signal_handler_unblock (gpointer instance,gulong   handler_id);
void g_signal_handlers_unblock_by_func( gpointer object,GCallback func,gpointer data );

2.3 信号连接函数 g_signal_connect_swapped

/*信号连接函数*/
#define g_signal_connect_swapped(instance, detailed_signal, c_handler, data)
g_signal_connect_swapped()和g_signal_connect() 相同,只是回调函数只用一个参数,一个指向GTK对象的指针。所以当使用这个函数连接信号时,回调函数应该是这样的形式:void callback_func( GtkObject *object );

  拥有两个函数来设置信号连接的目的只是为了允许回调函数有不同数目的参数。GTK 库中许多函数仅接受一个单独的构件指针作为其参数,所以对于这些函数你要用 g_signal_connect_swapped(),然而对你自己定义的函数,你可能需要附加的数据提供给你的回调函数。

3 事件

  除有信号机制外,还有一套 events 反映 X 事件机制。回调函数可以与这些事件连接。

• event
• button_press_event
• button_release_event
• scroll_event
•motion_notify_event
• delete_event
• destroy_event
• expose_event
• key_press_event
• key_release_event
• enter_notify_event
• leave_notify_event
• configure_event
• focus_in_event
• focus_out_event
• map_event
• unmap_event
• property_notify_event
• selection_clear_event
• selection_request_event
• selection_notify_event
• proximity_in_event
• proximity_out_event
• visibility_notify_event
• client_event
• no_expose_event
• window_state_event

  为了连接一个回调函数到这些事件之一,你使用函数 g_signal_connect(),像前面介绍的一样,用上面事件名之一作为detailed_signal参数。事件的回调函数与信号的回调函数有一点点不同:

gint callback_func( GtkWidget *widget,GdkEvent *event,gpointer callback_data );

  GdkEvent 是一个C联合结构,它的类型依赖于上述事件中的哪个事件发生了。为了让我们得知发生了哪个事件,每个可能的类型都有一个type成员来反映发生的事件。事件结构的其它部分将依赖于这个事件的类型。类型的可能的值有:

GDK_NOTHING
GDK_DELETE
GDK_DESTROY
GDK_EXPOSE
GDK_MOTION_NOTIFY
GDK_BUTTON_PRESS
GDK_2BUTTON_PRESS
GDK_3BUTTON_PRESS
GDK_BUTTON_RELEASE
GDK_KEY_PRESS
GDK_KEY_RELEASE
GDK_ENTER_NOTIFY
GDK_LEAVE_NOTIFY
GDK_FOCUS_CHANGE
GDK_CONFIGURE
GDK_MAP
GDK_UNMAP
GDK_PROPERTY_NOTIFY
GDK_SELECTION_CLEAR
GDK_SELECTION_REQUEST
GDK_SELECTION_NOTIFY
GDK_PROXIMITY_IN
GDK_PROXIMITY_OUT
GDK_DRAG_ENTER
GDK_DRAG_LEAVE
GDK_DRAG_MOTION
GDK_DRAG_STATUS
GDK_DROP_START
GDK_DROP_FINISHED
GDK_CLIENT_EVENT
GDK_VISIBILITY_NOTIFY
GDK_NO_EXPOSE
GDK_SCROLL
GDK_WINDOW_STATE
GDK_SETTING

  所以, 连接一个回调函数到这些事件之一,我们会这样用:

g_signal_connect (G_OBJECT (button), "button_press_event",G_CALLBACK (button_press_callback), NULL);

  这里假定button是一个按钮构件。现在,当鼠标位于按钮上并按一下鼠标时,函数 button_press_callback() 会被调用。这个函数应该声明为:

static gint button_press_callback( GtkWidget *widget,GdkEventButton *event,gpointer data );

  注意,我们可以把第二个参数类型声明为 GdkEventButton,因为我们知道哪个类型的事件会发生。
  这个函数的返回值指示这个事件是否应该由 GTK 事件处理机制做进一步的传播。 返回 TRUE 指示这个事件已经处理了,且不应该做进一步传播。 返回 FALSE 继续正常的事件处理。

3.1 按键连接信号关闭窗口示例

#include <gtk/gtk.h>
void hello(GtkWidget *widget,gpointer data)
{g_print("按键信号触发成功\n");
}
/*事件处理回调函数*/
gint delete_event(GtkWidget *widget,GdkEvent *evnet,gpointer data)
{g_print("事件处理回调函数调用成功\n");return TRUE;//TRUE表示继续,FALSE表示关闭
}void destroy(GtkWidget *widget,gpointer data)
{g_print("销毁窗口\n");gtk_main_quit();//退出程序
}
int main(int argc,char *argv[])
{GtkWidget *window;GtkWidget *button;/*gtk初始化*/gtk_init(&argc, &argv);/*创建窗口*/window=gtk_window_new(GTK_WINDOW_TOPLEVEL);gtk_window_set_title(GTK_WINDOW(window),"GTK");/*设置窗口标题*//*信号连接函数*/g_signal_connect(GTK_OBJECT(window),"delete_event",G_CALLBACK(delete_event),NULL);g_signal_connect(GTK_OBJECT(window),"destroy", G_CALLBACK(destroy), NULL);/*设置容器对象属性:设置窗口边框宽度为100*/gtk_container_set_border_width(GTK_CONTAINER(window),100);/*创建新的按钮,设置按钮信息为hello*/button=gtk_button_new_with_label("hello");g_signal_connect(GTK_OBJECT(button),"clicked",G_CALLBACK(hello),NULL);g_signal_connect_swapped(GTK_OBJECT(button),"clicked",G_CALLBACK(gtk_widget_destroy),GTK_OBJECT(window));/*将按钮放入窗口中*/gtk_container_add(GTK_CONTAINER(window),button);/*显示控件*/gtk_widget_show_all(window);/*等待事件*/gtk_main();return 0;
}

  • 程序运行效果:

  当我们用鼠标按下hello按钮,按键发出clicked信号,触发hello回调函数,接着调用下一个信号处理函数gtk_widget_destroy(),将窗口构件参数传递给该函数,销毁窗口,从而窗口发出destroy信号,然后调用我们实现号的回调函数destroy(),实现程序退出。

GTK之信号和回调函数相关推荐

  1. C语言 sigaction函数捕捉信号 注册回调函数

    // ..使用内存映射可以拷贝文件 /* 对原始文件进行内存映射 创建一个新文件 把新文件的数据拷贝映射到内存中 通过内存拷贝将第一个文件的内存映射区拷贝到第二个文件的内存映射区 释放资源 */// ...

  2. C语言 信号集回调函数 避免子进程在信号回调注册完成之前全部结束

    // ..使用内存映射可以拷贝文件 /* 对原始文件进行内存映射 创建一个新文件 把新文件的数据拷贝映射到内存中 通过内存拷贝将第一个文件的内存映射区拷贝到第二个文件的内存映射区 释放资源 */// ...

  3. python gui button回调函数运行完成后弹出窗口_嵌入式设备GUI开发之GTK+入门(一)...

    小伙伴们大家好,最近鑫哥带领大家做了很多的C语言的小项目,那有些小伙伴说我们可以用python做图形界面,我们可以使用C语言做吗? 我的回答是当然没问题嘻嘻,接下来鑫哥就带大家一起去看看如何进行GTK ...

  4. QT信号与槽——观察者模式——回调函数

    QT信号与槽--观察者模式--回调函数 1.QT信号与槽机制 1.1信号本质 信号是由于用户对窗口或控件进行了某些操作,导致窗口或控件产生了某个特定事件,这时候 Qt 对应的窗口类会发出某个信号.比如 ...

  5. C语言signal()函数(通过设置一个函数(回调函数)来处理捕获到异常信号时需要执行的操作)

    文章目录 描述 声明 参数 返回值 实例 附加解释 背景知识:C语言中signal函数简介及使用 描述 C 库函数 void (*signal(int sig, void (*func)(int))) ...

  6. linux操作系统信号捕捉函数之回调函数小结

    (1)signal 信号捕捉函数:注册一个信号捕捉函数(不参与捕捉,那是内核的事情) 函数实现: typedef   void(*sighandler_t)(int);   //声明了一个函数指针(代 ...

  7. 网络编程之 信号捕捉器(函数指针与回调函数)

    接着我们的信号说下去      之前博主给大家分享到了信号的概念和初步介绍signal函数的形式后就没有继续往下介绍了,实在是因为时间不够,那个时候博主还要上课,现在博主放假了就好好给大家分享一下如何 ...

  8. 在Qt中使用回调函数替代信号槽

    前言 在Qt中传数据,我们使用了一个信号和槽系统,但这并不意味着不能使用旧的经过验证的方法,即使用 CallBack回调函数功能. 事实上使用 CallBack 功能比信号和槽要快一些.并且当发送信号 ...

  9. linux通过信号回调函数,信号机制的管理结构 - Linux内核中的信号机制_Linux编程_Linux公社-Linux系统门户网站...

    信号只是一个数字,数字为0-31表示不同的信号,如下表所示. 编号 信号名 默认动作 说明 1 SIGHUP 进程终止 终端断开连接 2 SIGINT 进程终止 用户在键盘上按下CTRL+C 3 SI ...

最新文章

  1. zabbix 实践 (一)
  2. 禁止 pdf 下载、打印的方法
  3. 2020年, image captioning论文汇总
  4. 如何在IE让用户自动下载ActiveX控件?
  5. gini系数 决策树_案例7:机器学习--使用决策树实现泰坦尼克号乘客生存率预测...
  6. 2.2 决策树原理与算法——python实战
  7. 训练一个简单的游戏AI(Deep Q Network)
  8. spring 事务源码分析(四)传播机制总览
  9. 基于Android平台的三维实时全景地图设计与实现(一)
  10. matlab 中常用的日期格式转换
  11. Mp4box的下载、安装和使用
  12. 中兴网络设备交换机路由器查看日志命令方法
  13. linux命令清理磁盘空间,Linux如何使用命令行清理磁盘来增加空间
  14. 人工智能时代党政人力资源的思考与变化
  15. P2123 皇后游戏 (贪心+公式推导)
  16. FT5316调试记录
  17. 解决STM32F0/F1内部FLASH写操作导致中断程序无法响应的问题
  18. Mysql Unique Key 报错 Duplicate
  19. HDOJ 2026 首字母变大写
  20. linux 6新扩分区识别,虚拟机中CentOS 6.5 添加扩展分区

热门文章

  1. html中的那些炫酷吊炸天的操作
  2. 盘点 2021 年十大网络安全事件
  3. 公司邮箱、公共邮箱、工作邮箱,常用什么邮箱?
  4. 连连支付提现人民币的时候汇率是怎么样的?
  5. 1.3寸OLED IIC驱动右方出现两列像素白边的解决方法
  6. Notepad++常用插件下载地址
  7. 蚂蚁花呗的交易分期(有别于账单分期)
  8. 自媒体多平台多账号群发工具开发日记:第1天 工具的统筹规划
  9. 【规划】常用算法大汇总
  10. 风潮唱片-远方的寂静;专辑