gpt4 book ai didi

c - 如何使用回调修改 GtkWidget 数组的元素

转载 作者:太空宇宙 更新时间:2023-11-04 04:20:44 26 4
gpt4 key购买 nike

我需要编写一个回调来更改存储在 GtkWidget 数组中的标签的字体颜色。

当前状态的代码在这里 https://github.com/dustynine/colta-gtk/blob/struct/src/main.c

在初始化接口(interface)的函数中,我的数组如下所示:

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

我在 gdb 中挑选了一下,根据 explore pw -> cls[0]:

'pw -> cls[0]' is a pointer to a value of type 'GtkWidget'

那么,我该如何使它按预期工作呢?我怀疑我要么错误地将数组分配给结构(但这是程序工作的唯一方式),要么在回调结束时尝试修改它时错误地访问它。


编辑: 我按照 liberforce 的建议重写了程序。为我的图形用户界面创建了一个结构:

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 导致 Segmentation fault

最佳答案

我想我明白了。我在 main()

之外创建结构原型(prototype)
struct template {
GtkWidget *window;
...
GtkWidget *plaintext;
GtkWidget *cells[CELLS];
};

然后在应用程序的“激活”信号上调用的回调中,我这样做:

static void activate(GtkApplication* app, gpointer user_data) {
static struct template gui;

gui.plaintext = gtk_entry_new();
printf("gui.plaintext address: %p\n", gui.plaintext);

g_signal_connect(
G_OBJECT(gui.button),
"clicked",
G_CALLBACK(encode),
&gui
);

在编码回调中我有这个

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);

GdkColor color;
gdk_color_parse("#ff0000", &color);
gtk_widget_modify_fg(GTK_WIDGET(pw -> cells[0]), GTK_STATE_NORMAL,
&color);
}

现在一切正常。基本上,我通过将 static 添加到 activate 回调中的 struct template gui 声明来解决我的问题。我将在 github 上保留该文件的工作版本的链接以供将来引用。感谢 liberforce 为我指明了正确的方向。

关于c - 如何使用回调修改 GtkWidget 数组的元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47185272/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com