我有GTK GUI,它有一个控制按钮,在我的结构中打开一个名为c_window
的新窗口。c_window
有一个退出按钮,我需要连接到c_quit
功能。当我尝试这样做时,窗口不会终止,每次我按下退出按钮时都会出现警告:
(main_menu:2682): Gtk-CRITICAL **: 06:30:38.469: gtk_widget_destroy: assertion 'GTK_IS_WIDGET (widget)' failed
我的c_quit
函数是:
static gboolean c_quit (gpointer userData)
{
message_details *details = (message_details *)userData;
gtk_widget_destroy (details->c_window);
return FALSE;
}
如何与主
连接g_signal_connect(G_OBJECT(details->c_quit), "clicked", G_CALLBACK (c_quit), details->c_window);
请注意,details
是我定义GtkWidget
元素的结构体。
首先,你的信号连接函数是:
g_signal_connect(G_OBJECT(details->c_quit), "clicked", G_CALLBACK (c_quit), details->c_window);
包含details->c_quit
不必要的强制类型转换。此外,您正在传递details
指针的c_window
字段。
接下来,你的回调是:
static gboolean c_quit (gpointer userData)
{
message_details *details = (message_details *)userData;
gtk_widget_destroy (details->c_window);
return FALSE;
}
在回调GtkButton::clicked
信号时签名错误;正确的签名应该是:
static void
c_quit (GtkButton *button, gpointer data)
另外,我建议为回调使用一个合适的函数名,这样你就可以很容易地理解它的作用,以及它在哪里被引用。例如,某物quit_button__clicked
.
在你的回调函数中,你使用错误的类型访问了错误的形参:
message_details *details = (message_details *)userData;
因为你没有传递details
数据,你传递的是一个指向窗口本身的指针。另外,gpointer
是void*
的别名,C允许隐式转换到void*
;这意味着您不需要在这里进行显式强制转换。
总结一下:
- 正确连接信号,使用正确的参数发送到你的回调:
g_signal_connect (details->c_quit, "clicked",
G_CALLBACK (quit_button__clicked),
details);
- 为你连接的信号使用正确的原型,并访问正确的数据:
static void
quit_button__clicked (GtkButton *button G_GNUC_UNUSED,
gpointer user_data)
{
message_details *details = user_data;
gtk_widget_destroy (details->c_window);
}
如果您只是想调用窗口小部件上的gtk_widget_destroy()
来响应GtkButton
上的clicked
信号,您也可以将所有内容压缩为单个调用:
g_signal_connect_swapped (details->c_quit, "clicked",
G_CALLBACK (gtk_widget_destroy),
details->c_window);
g_signal_connect_swapped()
函数将在调用回调时交换信号的第一个和最后一个参数——第一个参数是发出信号的实例,最后一个参数是传递给连接函数的用户数据。这意味着gtk_widget_destroy()
将使用g_signal_connect_swapped()
的user data参数来调用。