0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看威廉希尔官方网站 视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

GTK之信号和回调函数

嵌入式威廉希尔官方网站 来源:嵌入式威廉希尔官方网站 作者:嵌入式威廉希尔官方网站 2022-11-24 08:32 次阅读

  在 2.0 版,信号系统已从 GTK 移到 GLib,因此在函数和类型的说明中有前缀 “g_” 而不是 “gtk_”。

GTK 是一个事件驱动的工具包,意味着它会等在gtk_main() 那里, 直到下一个事件发生, 才把控制权传给适当 的函数。控制权的传递是使用“信号”的办法来完成的。(注意这里的信号并不等同于Unix 系统里的信号,并且也不是用它们实现的,虽然使用的术语是一样的。)

1.常用信号

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

构件 信号 意义 产生信号函数
windows “destroy” 关闭窗口时发出该信号
button “clicked” 点击按钮,这是按下和释放操作的组合 gtk_button_clicked(button)
“clicked” 点击按钮,这是按下和释放操作的组合 gtk_button_clicked(button)
“clicked” 点击按钮,这是按下和释放操作的组合 gtk_button_clicked(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 事件机制。回调函数可以与这些事件连接。

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 
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;
}
poYBAGN-u4qAVy5YAAAgfJueK9k675.png#pic_center

程序运行效果:

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

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 信号
    +关注

    关注

    11

    文章

    2791

    浏览量

    76760
  • 回调函数
    +关注

    关注

    0

    文章

    87

    浏览量

    11562
收藏 人收藏

    评论

    相关推荐

    一文详解C语言函数指针与函数

    在讲函数之前,我们需要了解函数指针。
    发表于 10-19 09:34 794次阅读

    C语言里面的函数指针和函数

    在讲函数之前,我们需要了解函数指针。
    发表于 12-13 10:28 636次阅读

    C语言函数学习

    对指针的应用是C语言编程的精髓所在,而回函数就是C语言里面对函数指针的高级应用。简而言之,函数
    发表于 05-27 09:44 7206次阅读

    LabWindows/CVI 程序 函数设计

    函数是系统框架设计中非常重要的一种手段,所谓函数(callback )是指一个通过
    发表于 05-03 16:54 1.1w次阅读
    LabWindows/CVI 程序 <b class='flag-5'>回</b><b class='flag-5'>调</b><b class='flag-5'>函数</b>设计

    函数的详细资料说明

    异步事件的处理,首先将异步事件发生时需要执行的代码编写成一个函数,并将该函数注册成为函数,这样当该异步事件发生时,系统会自动调用事先注册
    发表于 02-28 08:00 6次下载
    <b class='flag-5'>回</b><b class='flag-5'>调</b><b class='flag-5'>函数</b>的详细资料说明

    C语言函数函数

    来源:嵌入式客栈 1 什么是函数?首先什么是呢? 我的理解是:把一段可执行的代码像参数传递那样传给其他代码,而这段代码会在某个时刻被
    的头像 发表于 09-11 09:57 4134次阅读

    STM32编程时,如何确定中断函数的入口

    STM32编程时,如何确定中断函数函数名换句话说,就是如何找到中断
    发表于 11-23 18:06 13次下载
    STM32编程时,如何确定中断<b class='flag-5'>回</b><b class='flag-5'>调</b><b class='flag-5'>函数</b>的入口

    详解函数的概念及使用步骤

    函数就是一个被作为参数传递的函数。在C语言中,函数
    的头像 发表于 05-26 15:20 4034次阅读

    一文详解C/C++函数

    首先看一下函数的官方解释:函数就是一个通过函数
    的头像 发表于 02-12 09:20 1596次阅读

    函数指针和函数的使用方法

    了解开发语言的朋友应该都会对函数有所了解,在很多的程序开发语言中都能看到的身影。很多场景下,当某个条件成立以后我们希望代码执行某些指
    的头像 发表于 04-10 15:08 1106次阅读

    C语言技巧函数

    在讲函数之前,我们需要了解函数指针。
    的头像 发表于 04-18 11:50 787次阅读

    C语言|函数的不同用法

    函数是个高级操作技巧,也是日常项目中常常使用到的技能。之所以说函数是个高级操作技巧,是因
    发表于 07-10 10:34 1314次阅读

    应用笔记 | 浅谈STM32库里的函数

    关键字:函数,HAL库   目录预览 1.函数 2.STM32固件库里的
    的头像 发表于 09-14 17:10 3665次阅读
    应用笔记 | 浅谈STM32库里的<b class='flag-5'>回</b><b class='flag-5'>调</b><b class='flag-5'>函数</b>

    ​​嵌入式中函数的实现方法

    函数的命名规范没有固定的标准,但是根据通用惯例和编码规范,函数的命名应该能够反映
    发表于 03-04 14:49 723次阅读

    函数(callback)是什么?函数的实现方法

    函数是一种特殊的函数,它作为参数传递给另一个函数,并在被调用函数执行完毕后被调用。
    发表于 03-12 11:46 2940次阅读