GTK下Notebook的信号绑定
Notebook下有10个信号:change_current_page, create_window, focus_tab, move_focus_out, page_added, page_removed, page_reordered,
reorder_tab, select_page, switch_page。
这些信号我怎样也不能绑定到回调函数上,不知道哪里错了,有谁能教教我。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
{:2_172:}
我明白了。
这让我想起了看Sqlite3的源码。sqlite3_exec()函数的call_back也是用同样的原理完成回调的参数传递。我的想法还是不够OPEN,以前看过的东西都没能运用起来。{:2_180:}
谢谢nketc。你给我上了一课。
本帖最后由 nketc 于 2011-03-14 21:20 编辑
回复 7# fengtom_lcdtv
对了一半。
是正确的,可是下面就不对了。我们应该按照gtk文档中signal callback的原型来定义函数,然后通过 g_signal_connect注册为回调。
你又把 my_function定义成了这个样子:
复制代码就不对了。
看看gtk定义 change-current-page的地方:
复制代码在这个文件http://git.gnome.org/browse/gtk+/tree/gtk/gtknotebook.c的970行,其中_gtk_marshal_BOOLEAN__INT就指明了callback的原型。
在glib的http://git.gnome.org/browse/glib/tree/gobject/gclosure.c 第788行就是调用我们注册的回调函数的地方:
复制代码这儿的 marshal 这个函数指针就是定义信时的_gtk_marshal_BOOLEAN__INT, _gtk_marshal_BOOLEAN__INT的代码为:
复制代码标记为 708的这一行的 callback 就是 我们用 g_signal_connect 注册的那个回调。
明白了吧?看到了把:这个callback就是按照gtk文档中 change-current-page 回调的原型调用的!
下面是个例子:
复制代码在 notebook_page_change加个断点,gdb一下:
复制代码够清晰了吧。
注意:
change-current-page 这个信号需要按 Ctrl+PageDown/PageUP 才能触发。pagedown的时候 回调的第二个参数(arg1)是1,
pageup的时候是-1,不论pagedown还是pageup 第三个参数都是我们写给 g_signal_connect的最后一个:255.
另外 "change-current-page" 和 "change_current_page" gtk不做区分。
下面是运行结果:
Screenshot-4.png (11.9 KB, 下载次数: 5)
下载附件
2011-03-14 21:17 上传
首先感谢nketc的耐心指点。
你说的有句话我理解得不清楚“gtk中定义signal的地方同时也指明了该signal回调的原型,gtk会按照这个原型调用你注册的函数。”
我们还举信号“change-current-page”的例子:
所谓“gtk中定义signal的地方同时也指明了该signal回调的原型”,我觉得是
gboolean user_function (GtkNotebook *notebook,
gint arg1,
gpointer user_data) : Action
另外“gtk会按照这个原型调用你注册的函数。”,那么就是说GTK会按照上面的 user_function来处理信号“change-current-page”,所以我也需要定义一个my_function(GtkNotebook *notebook, gint arg1, gpointer user_data)的函数。然后通过
g_signal_connect(GTK_OBJECT(notebook), "change_current_page", G_CALLBACK(my_function), (gpointer)(data));
来连接这个信号。
我可以自定义一个结构体data,里面包括成员变量:arg1与user_data。但是后面该怎么做呢?
void my_function(GtkNotebook *widget, gpointer data)
{
user_function(widget, data.arg1, data.user_data); // ??????????
}
这里搞不清楚。
另外,我没有接触过Win32 SDK编程。希望你能详细讲解一下。谢谢!
回复 5# fengtom_lcdtv
看来你对什么是回调不是很理解。比如某个软件模块要求的回调原型是 void foo(int a, int b),你向这个软件模块注册回调的时候该模块保存了你注册的函数的地址,比如说保存到了 callback。该模块在需要的时候如下调用 (*callback)(2, 3);
不知道这样说你明白了没有。
gtk中定义signal的地方同时也指明了该signal回调的原型,gtk会按照这个原型调用你注册的函数。
至于你说的 g_signal_connect 的时候只能给 callback传递一个参数,其实回调的参数没有一个是你传递的(你有像一般的函数调用一样调用过回调吗?),回调是gtk内部调用的,至于给回调传递什么样的参数是定义signal的时候就确定了,而参数的值根据你程序的执行情况确定。一般gtk的signal回调最后都有一个自定义的参数,利用它用户可以传递一些上下文信息。你说的只能传一个参数,就是这个自定义的参数。gtk负责把你写给g_signal_connect的最后一个参数传递给你注册的回调的最后一个形参。
不知道你有没有接触过 Win32 SDK编程,那里面的窗口过程函数 就是一个典型的回调。
举例来说:信号"change-current-page"
gboolean user_function (GtkNotebook *notebook,
gint arg1,
gpointer user_data) : Action
所以,连接该信号需要传递两个参数:(arg1, user_data)。
而g_signal_connect()只能给回调函数g_callback传递一个参数。
请问该怎么解决?
g_signal_connect 用法没错,但是signal的callback原型错了,请参考:http://library.gnome.org/devel/g ... ebook-create-window
g_signal_connect(GTK_OBJECT(notebook), "change_current_page", G_CALLBACK(notebook_single_check), (gpointer)(1));
g_signal_connect(GTK_OBJECT(notebook), "create_window", G_CALLBACK(notebook_single_check), (gpointer)(2));
g_signal_connect(GTK_OBJECT(notebook), "focus_tab", G_CALLBACK(notebook_single_check), (gpointer)(3));
g_signal_connect(GTK_OBJECT(notebook), "move_focus_out", G_CALLBACK(notebook_single_check), (gpointer)(4));
g_signal_connect(GTK_OBJECT(notebook), "page_added", G_CALLBACK(notebook_single_check), (gpointer)(5));
g_signal_connect(GTK_OBJECT(notebook), "page_removed", G_CALLBACK(notebook_single_check), (gpointer)(6));
g_signal_connect(GTK_OBJECT(notebook), "page_reordered", G_CALLBACK(notebook_single_check), (gpointer)(7));
g_signal_connect(GTK_OBJECT(notebook), "reorder_tab", G_CALLBACK(notebook_single_check), (gpointer)();
g_signal_connect(GTK_OBJECT(notebook), "select_page", G_CALLBACK(notebook_single_check), (gpointer)(9));
g_signal_connect(GTK_OBJECT(notebook), "switch_page", G_CALLBACK(notebook_single_check), (gpointer)(10));
void notebook_single_check(GtkNotebook *widget, gpointer data)
{
switch((gint)(data))
{
case 1: g_print("change-current-pagen"; break;
case 2: g_print("create-windown"; break;
case 3: g_print("focus-tabn"; break;
case 4: g_print("move-focus-outn"; break;
case 5: g_print("page-addedn"; break;
case 6: g_print("page-removedn"; break;
case 7: g_print("page-reorderedn"; break;
case 8: g_print("reorder-tabn"; break;
case 9: g_print("select-pagen"; break;
case 10: g_print("switch-pagen"; break;
default: g_print("signal error %dn", (gint)(data)); break;
}
}
用g_signal_connect连接信号,用函数void notebook_single_check(GtkNotebook *widget, gpointer data)检验连接的信号。
应该是g_signal_connect用错了吧!但我也没有找到其它适合的函数做连接信号用。
到底是哪里错了呢?
你代码怎么写的?