2012-01-08 69 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