信号和回调函数的原理:
Note:
在 2.0 版,信号系统已从 GTK 移到 GLib,因此在函数和类型的说明中有前缀 “g_” 而不是 “gtk_”
。
我们不打算介绍 GLib 2.0 信号系统相对 GTK 1.2 信号系统扩展的细节。
在我们详细分析 Hello World 程序之前,我们会先在这里讨论信号和回调函数。
GTK 是一个事件驱动的工具包,意味着它会等在 gtk_main() 那里,直到下一个事件发生,才把控制权传给适当的函数。
控制权的传递是使用“信号”的办法来完成(注意这里的信号并不等同于 Unix 系统里的信号,并且也不是用它们实现的,虽然使用的术语是一样的)。 GTK 的工作机制是:当一个事件发生时(例如:按一下鼠标键),所按的构件会“发出”适当的“信号”。
在“信号”中存在以下情况:
- 共有的信号:所有构件都继承的信号
例如: “destroy”;- 自己的信号:构件有自己专有的信号
例如:开关 toggle 按钮发出的 “toggled” 信号;
控件绑定信号有以下两种函数形式,同时也对应两种回调函数形式:
控件绑定信号函数 形式1:
要使一个按钮执行一个动作,需设置信号和信号处理函数之间的连接,我们可以这样使用函数来设置连接:
gulong g_signal_connect( gpointer *object,
const gchar *name,
GCallback func,
gpointer func_data );
参数:
object 第1个参数是要发出信号的构件
name 第2个参数是你想要连接的信号的名称
func 第3个参数是信号被捕获时所要调用的函数
func_data 第4个参数是你想传递给这个函数的数据
第3个参数指定的函数叫做回调函数,一般为下面的形式:
void callback_func( GtkWidget *widget,
gpointer callback_data );
参数:
第一个参数是一个指向发出信号的构件的指针
第二个参数是一个指向数据的指针,就是上面 g_signal_connect() 函数的最后一个参数传进来的数据。
注意:上面回调函数的声明只是一般的形式,有些构件的特殊信号会用不同的调用参数。
控件绑定信号函数 形式2:
另一个在 Hello World 示例中使用的调用,是:
gulong g_signal_connect_swapped( gpointer *object,
const gchar *name,
GCallback func,
gpointer *slot_object );
g_signal_connect_swapped() 和 g_signal_connect() 相同,只是回调函数只用一个参数,一个指向 GTK 对象的指针。所以当使用这个函数连接信号时,回调函数应该是这样的形式
void callback_func( GtkObject *object );
这个对象通常是一个构件。然而我们一般不用函数 g_signal_connect_swapped() 设置回调。它们常用来调用一个只接受一个单独的构件或者对象作为参数的 GTK 函数,如同我们的 Hello World 示例中那样。
以上两种函数的联系和区别:
拥有两个函数来设置信号连接的目的只是为了允许回调函数有不同数目的参数。GTK 库中许多函数仅接受一个单独的构件指针作为其参数,所以对于这些函数你要用 g_signal_connect_swapped(),然而对你自己定义的函数,你可能需要附加的数据提供给你的回调函数。