【发布时间】:2017-11-08 16:48:27
【问题描述】:
我需要编写一个回调来更改存储在 GtkWidget 数组中的标签的字体颜色。
当前状态的代码在这里https://github.com/dustynine/colta-gtk/blob/struct/src/main.c
在初始化接口的函数中,我的数组如下所示:
GtkWidget *cells[CELLS];
for (int i=0; i<CELLS; i++) {
cells[i] = gtk_label_new("██");
}
连接到按钮的回调:
g_signal_connect(
G_OBJECT(button),
"clicked",
G_CALLBACK(encode),
make_data(plaintext, key, cells)
);
make_data() 是一个返回带有回调参数的结构的函数:
struct passed_widgets {
GtkWidget *plaintext;
GtkWidget *key;
GtkWidget **cls;
};
gpointer make_data(GtkWidget *text, GtkWidget *key, GtkWidget *cells[CELLS]) {
static struct passed_widgets pw;
pw.plaintext = text;
pw.key = key;
pw.cls = cells;
return (gpointer) &pw;
}
在回调内部我有这个:
static void encode(GtkButton *button, gpointer *data) {
struct passed_widgets *pw;
GdkColor color;
pw = (struct passed_widgets *) data;
gdk_color_parse("#07d9d9", &color);
gtk_widget_modify_fg(GTK_WIDGET(pw -> cls[0]), GTK_STATE_NORMAL, &color);
}
编译器不会抱怨(除了警告不推荐使用与颜色相关的东西)但是当我实际按下按钮时,Gtk 会报告:
(colta-gtk:3993): GLib-GObject-WARNING **: invalid uninstantiatable type 'GInterface' in cast to 'GtkWidget'
(colta-gtk:3993): Gtk-CRITICAL **: gtk_widget_modify_fg: assertion 'GTK_IS_WIDGET (widget)' failed
根据explore pw -> cls[0],我在gdb中挑选了一下:
'pw -> cls[0]' is a pointer to a value of type 'GtkWidget'
那么,我该如何按预期进行这项工作?我怀疑我要么错误地将数组分配给结构(但这是程序工作的唯一方式),要么在回调结束时尝试修改它时错误地访问它。
编辑:我按照 liberforce 的建议重写了程序。为我的 gui 创建了一个结构:
struct template {
GtkWidget *window;
...
GtkWidget *plaintext;
GtkWidget *cells[CELLS];
};
现在我只是将我实例化为gui 的这个结构传递给回调:
g_signal_connect(
G_OBJECT(gui.button),
"clicked",
G_CALLBACK(encode),
&gui
);
但是我再也无法在 encode() 函数中工作了:
static void encode(GtkButton *button, gpointer data) {
gchar *plaintext;
struct template *pw;
pw = (struct template *) data;
plaintext = gtk_entry_get_text(GTK_ENTRY(pw -> plaintext));
printf(" plaintext contents: %s\n", plaintext);
我又一次不明白出了什么问题。根据 gdb 类型匹配,编译器没有给出警告,但是当我运行程序并使用回调时,它给了我:
(colta-gtk:21589): Gtk-CRITICAL **: gtk_entry_get_buffer: assertion 'GTK_IS_ENTRY (entry)' failed
(colta-gtk:21589): Gtk-CRITICAL **: gtk_entry_buffer_get_text: assertion 'GTK_IS_ENTRY_BUFFER (buffer)' failed
地址如下:
gui.plaintext address: 0x55babcfc6290
gui address: 0x7ffd13fe8a88
&gui address: 0x7ffd13fe8910
data address: 0x7ffd13fe8910
pw address: 0x7ffd13fe8910
*pw address: 0x7ffd13fe8a88
pw -> plaintext address: (nil)
*pw -> plaintext 导致分段错误
【问题讨论】:
标签: c arrays struct callback gtk