- 论坛徽章:
- 5
|
本帖最后由 nketc 于 2011-03-14 21:20 编辑
回复 7# fengtom_lcdtv
对了一半。所以我也需要定义一个my_function(GtkNotebook *notebook, gint arg1, gpointer user_data)的函数。然后通过
g_signal_connect(GTK_OBJECT(notebook), "change_current_page", G_CALLBACK(my_function), (gpointer)(data));
来连接这个信号。
是正确的,可是下面就不对了。我们应该按照gtk文档中signal callback的原型来定义函数,然后通过 g_signal_connect注册为回调。
你又把 my_function定义成了这个样子:- void my_function(GtkNotebook *widget, gpointer data)
- {javascript:;
- user_function(widget, data.arg1, data.user_data); // ??????????
- }
复制代码 就不对了。
看看gtk定义 change-current-page的地方:- notebook_signals[CHANGE_CURRENT_PAGE] =
- g_signal_new (I_("change-current-page"),
- G_TYPE_FROM_CLASS (gobject_class),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (GtkNotebookClass, change_current_page),
- NULL, NULL,
- _gtk_marshal_BOOLEAN__INT,
- G_TYPE_BOOLEAN, 1,
- G_TYPE_INT);
复制代码 在这个文件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 (closure,
- return_value,
- n_param_values, param_values,
- invocation_hint,
- marshal_data);
复制代码 这儿的 marshal 这个函数指针就是定义信时的_gtk_marshal_BOOLEAN__INT, _gtk_marshal_BOOLEAN__INT的代码为:- 679 void
- 680 _gtk_marshal_BOOLEAN__INT (GClosure *closure,
- 681 GValue *return_value G_GNUC_UNUSED,
- 682 guint n_param_values,
- 683 const GValue *param_values,
- 684 gpointer invocation_hint G_GNUC_UNUSED,
- 685 gpointer marshal_data)
- 686 {
- 687 typedef gboolean (*GMarshalFunc_BOOLEAN__INT) (gpointer data1,
- 688 gint arg_1,
- 689 gpointer data2);
- 690 register GMarshalFunc_BOOLEAN__INT callback;
- 691 register GCClosure *cc = (GCClosure*) closure;
- 692 register gpointer data1, data2;
- 693 gboolean v_return;
- 694
- 695 g_return_if_fail (return_value != NULL);
- 696 g_return_if_fail (n_param_values == 2);
- 697
- 698 if (G_CCLOSURE_SWAP_DATA (closure))
- 699 {
- 700 data1 = closure->data;
- 701 data2 = g_value_peek_pointer (param_values + 0);
- 702 }
- 703 else
- 704 {
- 705 data1 = g_value_peek_pointer (param_values + 0);
- 706 data2 = closure->data;
- 707 }
- 708 callback = (GMarshalFunc_BOOLEAN__INT) (marshal_data ? marshal_data : cc->callback);
- 709
- 710 v_return = callback (data1,
- 711 g_marshal_value_peek_int (param_values + 1),
- 712 data2);
- 713
- 714 g_value_set_boolean (return_value, v_return);
- 715 }
复制代码 标记为 708的这一行的 callback 就是 我们用 g_signal_connect 注册的那个回调。
明白了吧?看到了把:这个callback就是按照gtk文档中 change-current-page 回调的原型调用的!
下面是个例子:- #include <gtk/gtk.h>
- gboolean notebook_page_change (GtkNotebook *notebook, gint arg1, gpointer data);
- int main (int argc, char* argv[])
- {
- GtkWidget *window;
- GtkWidget *notebook;
- GtkWidget *label;
- gint i;
- gchar *text;
- gtk_init (&argc, &argv);
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
- gtk_widget_set_size_request (window, 400, 300);
- notebook = gtk_notebook_new ();
- for (i=0; i<3; i++)
- {
- text = g_strdup_printf("hello label %02d", i + 1);
- label = gtk_label_new (text);
-
- gtk_notebook_append_page (GTK_NOTEBOOK (notebook), label, NULL);
- g_free (text);
- }
- g_signal_connect (notebook, "change-current-page",
- G_CALLBACK (notebook_page_change), (gpointer)255);
- gtk_container_add (GTK_CONTAINER(window), notebook);
- gtk_widget_show_all (window);
- gtk_main ();
- return 0;
- }
- gboolean
- notebook_page_change (GtkNotebook *notebook, gint arg1, gpointer data)
- {
- g_print("notebook=%p arg1=%d data=%d\n", notebook, arg1, (gint)data);
- return FALSE;
- }
复制代码 在 notebook_page_change加个断点,gdb一下:- #0 notebook_page_change (notebook=0x8087030, arg1=1, data=0xff) at notebook.c:45
- #1 0x002932ab in _gtk_marshal_BOOLEAN__INT (closure=0x8086e00, return_value=0xbfffe7b0,
- n_param_values=2, param_values=0x80eec98, invocation_hint=0xbfffe710, marshal_data=0x0)
- at gtkmarshalers.c:710
- #2 0x00bc4ada in g_closure_invoke (closure=0x8086e00, return_value=0xbfffe7b0, n_param_values=2,
- param_values=0x80eec98, invocation_hint=0xbfffe710) at gclosure.c:767
- #3 0x00bdc39d in signal_emit_unlocked_R (node=<value optimized out>, detail=<value optimized out>,
- instance=0x8087030, emission_return=0xbfffe7b0, instance_and_params=0x80eec98) at gsignal.c:3252
- #4 0x001921c0 in gtk_binding_entry_activate (entry=0x8083798, object=0x8087030) at gtkbindings.c:653
- #5 0x00193880 in binding_activate (binding_set=0x8083690, entries=0x80ee550, object=0x8087030,
- is_release=0, unbound=0xbfffe84c) at gtkbindings.c:1525
- #6 0x001939f2 in gtk_bindings_activate_list (object=0x8087030, entries=0x80ee550, is_release=0)
- at gtkbindings.c:1586
- #7 0x00193c43 in gtk_bindings_activate_event (object=0x8087030, event=0x80e2268)
- at gtkbindings.c:1671
- #8 0x00410054 in gtk_widget_real_key_press_event (widget=0x8087030, event=0x80e2268)
- at gtkwidget.c:5731
- #9 0x00292342 in _gtk_marshal_BOOLEAN__BOXED (closure=0x8073bd8, return_value=0xbfffea84,
- n_param_values=2, param_values=0x8097aa0, invocation_hint=0xbfffea70, marshal_data=0x410030)
- at gtkmarshalers.c:85
- #10 0x00bc3147 in g_type_class_meta_marshal (closure=0x8073bd8, return_value=0xbfffea84,
- n_param_values=2, param_values=0x8097aa0, invocation_hint=0xbfffea70, marshal_data=0xd8)
- at gclosure.c:878
- #11 0x00bc4a00 in g_closure_invoke (closure=0x8073bd8, return_value=0xbfffea84, n_param_values=2,
- param_values=0x8097aa0, invocation_hint=0xbfffea70) at gclosure.c:767
- #12 0x00bdc0c6 in signal_emit_unlocked_R (node=<value optimized out>, detail=<value optimized out>,
- ---Type <return> to continue, or q <return> to quit---
复制代码 够清晰了吧。
注意:
change-current-page 这个信号需要按 Ctrl+PageDown/PageUP 才能触发。pagedown的时候 回调的第二个参数(arg1)是1,
pageup的时候是-1,不论pagedown还是pageup 第三个参数都是我们写给 g_signal_connect的最后一个:255.
另外 "change-current-page" 和 "change_current_page" gtk不做区分。
下面是运行结果:
|
|