2012-01-08 62 views
3

我正在编写一个使用GTK库为接口的C游戏。这个想法是有两个主要容器:一个用于容纳按钮和其他小部件,让用户选择设置,另一个用于在实际游戏过程中显示和移动图像。我使用VBox来保存菜单部件,并使用固定容器来容纳游戏精灵。我这里有所有与该垂直框代码行和固定容器在main()方法:C Gtk问题:VBox添加到主窗口

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()之后,在将此容器添加到窗口时,有什么我不知道的吗?

回答

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

为什么浮动参照固定的容器没有迪e在调用gtk_main()之后?直到窗口小部件被添加到窗口之后,浮动引用是否继续存在? – 2012-01-08 20:24:48

+1

对'gtk_main'的调用对引用没有任何作用。是的,浮动参考会一直存在,直到它被沉没('g_object_ref_sink()')。通常它会将第一个(通常是唯一的)时间添加到容器中。 – rodrigo 2012-01-09 08:58:18