我正在使用GTK库为界面编写C游戏。我们的想法是拥有两个主要容器:一个用于容纳按钮,另一个用于让用户选择设置,另一个用于在实际游戏过程中显示和移动图像。我正在使用VBox来保存菜单小部件,并使用固定容器来保存游戏精灵。我在这里有main()方法中与VBox和Fixed容器相关的所有代码行:
GtkWidget* vbox;
GtkWidget* fixed;
...
int main(int argc, char** argv) {
// (The rest of this code block is in the main method)
...
// Make a vertical box for the menu widgets.
vbox = gtk_vbox_new(TRUE, 0);
// Add the menu widgets to the vbox.
gtk_box_pack_start(GTK_BOX(vbox), label1, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox), button1, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox), button2, TRUE, TRUE, 0);
gtk_box_pack_start(GTK_BOX(vbox), entry, TRUE, TRUE, 0);
// Make a new fixed container, which allows its children
// widgets to be moved dynamically.
fixed = gtk_fixed_new();
// Add the game widgets to the fixed container.
gtk_fixed_put(GTK_FIXED(fixed), player1, x, y);
gtk_fixed_put(GTK_FIXED(fixed), player2, x, y + 40);
gtk_fixed_put(GTK_FIXED(fixed), ball, x + 80, y);
gtk_fixed_put(GTK_FIXED(fixed), wall, x + 120, y);
// Add the fixed container to the window.
gtk_container_add(GTK_CONTAINER(window), vbox);
gtk_widget_show(vbox);
gtk_widget_show(fixed);
在我的一个按钮动作中,我有以下内容,以启动游戏玩法:
gtk_container_remove(GTK_CONTAINER(window), vbox);
gtk_container_add(GTK_CONTAINER(window), fixed);
哪个有效,没有任何问题。但是,在满足某个条件后,我会调用另一个函数,它执行相反的操作:
gtk_container_remove(GTK_CONTAINER(window), fixed);
gtk_container_add(GTK_CONTAINER(window), vbox);
这会导致以下问题:
(a.out:11762): Gtk-CRITICAL **: IA__gtk_container_add: assertion `GTK_IS_WIDGET (widget)' failed
我查看了小部件层次结构,并验证了VBox属于GtkWidget类别。当我最初将VBox添加到main()方法中的窗口时,没有发生上述错误。在调用gtk_main()之后将这个容器添加到窗口时,是否有一些我不知道的事情?
答案 0 :(得分:3)
问题是,GtkWidgets是引用计数但你没有任何引用。这通常用于GtkWidgets,因为只要窗口小部件可见,窗口系统就会保存一个对它们的引用。但只要从容器中删除小部件,引用计数就会降为零,并且会被销毁。
它第一次运行是因为有一个浮动引用,它就是在首次创建小部件之后存在的。
最简单的解决方案就是保存对两个移动窗口小部件的引用:在创建它们之后立即调用g_object_ref_sink
将浮动引用转换为实际引用。但是,当你完成它们时,别忘了打电话给g_object_unref
!
其他选项只是在移动计数器时递增/递减计数器,但您仍需要将引用隐藏到fixed
以按预期工作:
g_object_ref_sink(fixed);
然后:
g_object_ref(vbox);
gtk_container_remove(GTK_CONTAINER(window), vbox);
gtk_container_add(GTK_CONTAINER(window), fixed);
g_object_unref(fixed);
和
g_object_ref(fixed);
gtk_container_remove(GTK_CONTAINER(window), fixed);
gtk_container_add(GTK_CONTAINER(window), vbox);
g_object_unref(vbox);