C Gtk Issue: Добавление VBox в главное окно - PullRequest
3 голосов
/ 08 января 2012

Я пишу игру на C, используя библиотеку GTK для интерфейса.Идея состоит в том, чтобы иметь два основных контейнера: один для удерживания кнопок и другие виджеты, позволяющие пользователю выбирать настройки, а другой для отображения и перемещения изображений во время реального игрового процесса.Я использую VBox для хранения виджетов меню и фиксированный контейнер для хранения игровых спрайтов.Здесь у меня есть все строки кода, относящиеся к контейнерам VBox и Fixed в методе main ():

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 ()?

1 Ответ

3 голосов
/ 08 января 2012

Проблема в том, что 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);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...