GTK之信号和回调函数

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(),实现程序退出。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/69557.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

极智AI | AIGC时代中AI巨头之间的博弈

欢迎关注我的公众号 [极智视界],获取我的更多经验分享 大家好,我是极智视界,本文来谈谈 AIGC时代AI巨头之间的博弈。 邀您加入我的知识星球「极智视界」,星球内有超多好玩的项目实战源码下载,链接:https://t.zsxq.com/0aiNxERDq 下图是开复老师在 《AI 未来》演讲中一页…

基金经理二季度AI概念股操作分化

公募基金二季度仍在加仓AI板块&#xff0c;但不同于一季度全线加仓题材各环节&#xff0c;二季度对AI产业链的操作出现分化。 资金更加聚拢在业绩率先兑现的上游算力板块。其中光模块、服务器是加仓最为显著的两个领域&#xff1b;对于部分业绩短期兑现前景不明的AI板块&#…

调研27个模型后,代码生成的知识增加了

点击上方“AI遇见机器学习”&#xff0c;选择“星标”公众号 第一时间获取价值内容 来源&#xff5c;AINLPer 卷友们好&#xff0c;对于NL2Code任务相信大家都不陌生。它主要目的就是将自然语言转换成可执行代码来提高开发人员的工作效率&#xff0c;终极目标就是干翻所有程序员…

符尧:我想为 MOSS 正名

点击上方“AI遇见机器学习”&#xff0c;选择“星标”公众号 第一时间获取价值内容 知乎: Franx链接: https://www.zhihu.com/question/596908242/answer/2996276211编辑: 深度学习自然语言处理 公众号 我是符尧&#xff0c;是先前《拆解追溯 GPT-3.5 各项能力的起源》这篇文章…

inscode评测

文章目录 项目介绍首页使用反馈语言模板编辑AI模板​编辑网站模板编辑图形模板 编辑器使用反馈使用场景1---函数定位改进建议&#xff1a; 使用场景2---项目创建改进建议&#xff1a; 使用场景3---文件上传改进建议&#xff1a; 视觉反馈模板使用一些BUG反馈创建项目会较频繁出…

谷歌20年老员工叛逃,创立第二个OpenAI?

来源&#xff1a;新智元 硅谷独角兽&#xff0c;又来震撼世界了&#xff01; 这支名叫Character Technologies的独角兽的核心力量&#xff0c;来自前谷歌LaMDA团队。 他们的新产品在移动端上线不到一周&#xff0c;下载量就达到了170万&#xff0c;直接碾压了ChatGPT&#xff0…

技术无关性别,IT 界的“她”力量也能撬动半边天!

作者 | 朱珂欣 出品 | CSDN程序人生&#xff08;ID&#xff1a;coder_life&#xff09; 职业本无性别之分&#xff0c;但提到 IT 界的“程序员”&#xff0c;大家脑海中总会先浮现“格子衫、牛仔裤、戴眼镜”的模样&#xff0c;而并非人数比重较少的“程序媛”。据拉勾招聘数…

电脑同时登录多个微信

现在很多人手上都有多个手机号以及多个微信号&#xff0c;但我们发现&#xff0c;当我们想在电脑上同时登录多个微信&#xff0c;好像每次双击打开&#xff0c;都是跳出当前这一个&#xff0c;和QQ有很大的区别。 那我们可以通过bat文件来试试&#xff0c;通过执行bat文件里的…

电脑上同时登陆多个微信

电脑版微信默认只能登录一个微信&#xff0c;其实这里有个小技巧&#xff0c;无需安装任何软件&#xff0c;就能实现微信多开。 第一种方法&#xff1a; 按住键盘上的Shift键不要松手&#xff0c;然后鼠标快速多次点击微信图标&#xff0c;即可实现多开。&#xff08;这种方法…

电脑,从多人一台到一人多台

最早接触电脑是中学时&#xff0c;当时应该是APPLE-Ⅱ&#xff0c;固化的Basic&#xff0c;仅仅算是打了个照面&#xff0c;印象最深的就是空调机房&#xff0c;还有地毯&#xff0c;拖鞋&#xff08;当时还没有鞋套&#xff09;&#xff0c;功能倒是没有太多的概念。 到了大学…

19、两台电脑怎么就能互相通信了

今天的内容非常有趣,绝对让你涨知识~ 不知道大家是否好奇过这样一个问题,那就是,两台电脑怎么就能互相传递信息了呢?可能你觉得这是一件很正常的事情,就那样一发一接不就ok了嘛?可是真的让你说出个所以然,那绝对是触碰到你的知识盲区了~ 也许你学过之前的内容知道,这需…

多用户使用一台计算机 可设置,如何设置才能让一台计算机可以多个用户同时登陆?...

满意答案 adnx88234 2013.02.26 采纳率&#xff1a;55% 等级&#xff1a;13 已帮助&#xff1a;13511人 第一&#xff1a;共享的前提工作&#xff1a; 1.更改不同的计算机名&#xff0c;设置相同的工作组&#xff01; 2.我的电脑右键&#xff0d;管理&#xff0d;计算机管理…

chatgpt赋能python:Python数学建模:将数据转化为答案的利器

Python数学建模&#xff1a;将数据转化为答案的利器 随着数据时代的到来&#xff0c;数据的价值越来越受到人们的关注。但是单纯的数据没有意义&#xff0c;只有将他们转化成有意义的答案才有意义。在这个过程中&#xff0c;数学建模是一个非常重要的工具&#xff0c;而Python…

开发者藏经阁——超全阿里系电子书大合集(打包下载)

小白寻思着给大家发点福利&#xff0c;就整理了一下&#xff0c;阿里系电子书&#xff0c;有近80本&#xff0c;分享给大家&#xff0c;均可免费下载。 覆盖 Java、物联网、云原生、前端、大数据、开源、AI 等技术领域&#xff0c;深度分享阿里工程师实践精华&#xff0c;顶级…

阿里副总裁玄难:藏经阁计划研发大规模知识构建技术首次披露

导读&#xff1a;2018年4月&#xff0c;阿里联合清华大学、浙江大学、中科院自动化所、中科院软件所、苏州大学等五家机构&#xff0c;联合发布藏经阁&#xff08;知识引擎&#xff09;研究计划&#xff0c;同时还宣布打算用一年时间初步建成首个开放的知识引擎服务平台&#x…

互联网券商行业公司

中国券商在向互联网金融方向的拓展呈现了百花齐放的特点。对各个券商来说&#xff0c;在互联网证券业务方面在一定程度上尚缺乏或未来需要比较明确的长远目标。或者说&#xff0c;目前大家还都在摸着石头过河。但是&#xff0c;在中国大市场和互联网经济推动下&#xff0c;前途…

1元体验京东云服务器

1元体验京东云服务器 在大神鸿洋和郭霖的微信公众号推送文章发现了这个好消息&#xff0c;第一时间注册了账号&#xff0c;申请下了订单&#xff0c;毕竟数量有限。尽管两位大神讲的很详细&#xff0c;无奈没有接错过CentOS、Ubuntu、WindowsServer这些服务器系统的小白&#…

java简单代码运行内存图

java中主要的三块内存空间&#xff1a; 1.栈内存&#xff08;stack&#xff09;&#xff1a;在方法别调用时&#xff0c;栈内存会给方法分配内存&#xff08;压栈&#xff09;&#xff0c;主 要存储的是局部变量。方法调用结束后&#xff0c;该方法所占用的内存释放&#xff…

大厂程序员能力修炼手册,从筑基到化神要多久?

刚入行&#xff1a; 就是干 入行两年&#xff1a;熟知各种设计模式&#xff0c;信手拈来 入行三年&#xff1a;阅码无数&#xff0c;心中已无设计模式 入行五年&#xff1a;就是干 大家好&#xff0c;我是安酱。今天来跟大家聊聊程序员的能力进阶道路。 相信许多小伙伴都知道…

我的周刊(第001期)

我的信息周刊&#xff0c;记录这周我看到的有价值的信息&#xff0c;主要针对计算机领域&#xff0c;内容主题极大程度被我个人喜好主导。这个项目核心目的在于记录让自己有印象的信息做一个留存以及共享。 项目 image-to-latex[1] 可以将数学公式截图然后自动解析成LaTex输出&…