gpt4 book ai didi

c - GTK2+ 错误 : GTK_IS_CONTAINER & GTK_IS_WIDGET failed

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

这是我在这里的第一篇文章,我创建这个帐户是因为我有点难过。我正在尝试练习将结构作为参数传递给回调,为此我在窗口中创建了一个带有按钮的简单程序。在第一次迭代中,按下标签为“Button 1”的按钮会将其更改为标签为“Button 2”的不同按钮,而在第二次迭代中,通过将鼠标悬停在按钮上来完成更改。下面是第一次迭代的代码

#include <gtk/gtk.h>

typedef struct {
GtkWidget *button1;
GtkWidget *button2;
GtkWidget *window;
} example;

void callback_func (GtkWidget *ignored, example *test) {
GtkWidget *window=test->window;
GtkWidget *changebutton1=test->button1;
GtkWidget *changebutton2=test->button2;
gtk_container_remove(GTK_CONTAINER(window),changebutton1);
gtk_container_add(GTK_CONTAINER(window),changebutton2);
gtk_widget_show_all(window);
}
void callback_func2 (GtkWidget *ignored, example *test) {
GtkWidget *window=test->window;
GtkWidget *changebutton1=test->button1;
GtkWidget *changebutton2=test->button2;
gtk_container_remove(GTK_CONTAINER(window),changebutton2);
gtk_container_add(GTK_CONTAINER(window),changebutton1);
gtk_widget_show_all(window);
}

int main(int argc, char *argv[]) {
example test;
gtk_init(&argc,&argv);
GtkWidget *window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
GtkWidget *changebutton1=gtk_button_new_with_label("Button 1");
GtkWidget *changebutton2=gtk_button_new_with_label("Button 2");

test.window=window;
test.button1=changebutton1;
test.button2=changebutton2;

g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (gtk_main_quit), NULL);
g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (gtk_main_quit), NULL);


gtk_container_add(GTK_CONTAINER(window),changebutton1);
g_signal_connect (G_OBJECT (changebutton1), "clicked", G_CALLBACK (callback_func), (gpointer*)&test);
g_signal_connect (G_OBJECT (changebutton2),"clicked",G_CALLBACK(callback_func2),(gpointer*)&test);
gtk_widget_show_all(window);

gtk_main ();
return 0;
}

当运行上面的代码时,通过单击按钮一次,按钮会正确切换,但是当我再次单击它时(现在调用 callback_func2 而不是 callback_func,除了按钮切换位置外它们基本上是相同的)我得到这个:(gtktesting.exe:92024): Gtk-CRITICAL **: gtk_container_add: 断言 `GTK_IS_WIDGET (widget)' 失败

如果我用“enter_notify_event”和“leave_notify_event”替换“clicked”事件,第一个更改也会失败,现在会产生更多错误。

有人知道这是怎么回事吗?

另外,一个额外的问题。我几乎从另一篇文章中复制并粘贴了这段代码的基础,因为我一直试图自己编写它但没有成功,所以我想测试它是否有效。我注意到回调中的第二个参数是“example *test”。谁能解释“示例”类型?这只是结构的名称,我不知道它在那里做什么。

最佳答案

tl;dr

尝试:

test.window  = g_object_ref(window);
test.button1 = g_object_ref(changebutton1);
test.button2 = g_object_ref(changebutton2);

完整解释

GTK+ 中的对象(即 GObject 的子类)是引用计数的。这意味着,每个对象(例如 Widget)都有“引用计数”——指向它的指针的数量。当数字达到 0 - 对象被释放。创建的对象的引用计数为 1。由于 C 没有智能指针,C++ 也没有类似的东西,因此必须手动完成引用计数。用户必须调用 g_object_ref 才能保留引用(我交替使用“指针”和“引用”这两个词),并在用户完成引用后调用 g_object_unref。这确保没有对象在使用时被破坏。

GtkWidget 很特别,因为它以“ float ”引用开始生命。这意味着第一次引用小部件时,它的引用计数不会增加——它的“ float ”引用是“沉没”的。之后它的行为就像任何其他 GObject 一样。

当您创建按钮时,它们的引用计数为 1(“ float ”)。当它们被添加到它们的容器中时,它们的引用仍然是 1(但“沉没”)。这意味着,按钮由它们添加到的容器拥有

现在,当您从容器中移除按钮时:

gtk_container_remove(GTK_CONTAINER(window),changebutton1);

changebutton1 的引用计数减少,降至 0,这会强制对象销毁,并且 test.button1 现在是悬挂指针。

为了克服这个问题,只要您想要存储指向 GObject 的指针,请使用 g_object_ref。这样您就可以表达“test 参与了 changebutton1 的所有权”(或者,“test 有兴趣保留 changebutton1活着)。

完成 windowbutton1button2 后,对它们调用 g_object_unref

奖金问题

Also, a bonus question. I pretty much copied and pasted the base of this code from another post, since I had been trying to write it by myself unsuccessfully and I wanted to test if it works at all. I noticed that the second argument in the callbacks is "example *test". Can anybody explain the "example" type? It's only the name of the stucture, and I've no idea what it's doing there.

示例 定义如下:

typedef struct {
GtkWidget *button1;
GtkWidget *button2;
GtkWidget *window;
} example; // declares type "example"

GObject 信号系统的设计方式允许将任意指针作为最后一个参数传递给回调,因此程序员可以从创建信号连接的地方传递额外信息( g_signal_connect), 一个回调。

关于c - GTK2+ 错误 : GTK_IS_CONTAINER & GTK_IS_WIDGET failed,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31276404/

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