3.3.1 Жизненный цикл виджета

Управление ресурсами и памятью виджета почти автоматическое. Однако, существует несколько исключений (???), которые надо всегда помнить, когда вы делаете более сложные вещи.

Список функций 3..8: Удаление виджета
"#include "<gtk/gtkwidget.h>
void gtk_widget_destroy(GtkWidget *widget)

Виджет может быть удален в любое время вызовом функции "gtk_widget_destroy()" (показанной в списке функций 3..8); удаление виджета освобождает всю связанную с ним память и другие ресурсы. Если виджет находится внутри контейнера, он автоматически удаляется из контейнера перед своим разрушением. "gtk_widget_destroy()" является лишь другим именем для "gtk_object_destroy()"; Наследники GtkObject имеют виртуальные деструкторы, поэтому "gtk_object_destroy()" всегда все сделает правильно.

Внутри реализации для виджетов ведется счетчик ссылок (на самом деле, для всех GtkObject). Объекты начинают свою жизнь со счетчиком ссылок, равным 1, даже если на них еще ни разу не ссылались. В этой фазе об объекте можно сказать, что он плавающий, и ему присваивается это состояние. Можно удалить начальную ссылку на объект; это называется затопление плавающего объекта, и разрушить объект, если плавающая ссылка была равна единице.

Контейнер сначала ссылается на любой добавляемый виджет, а затем его затопляет. Затопляя виджет, контейнер становится его владельцем в целях управления его ресурсами. Поэтому, счетчик ссылок виджета остается равным 1, но объект уже не помечен как плавающий. Когда виджет удаляется из контейнера (или контейнер разрушается), счетчик ссылок уменьшается до 0. Когда счетчик ссылок объекта достигает 0, он разрушается.

На практике, это значит, что вам нужно разрушать только виджеты верхнего уровня; любые виджеты внутри контейнера будут разрушены вместе с контейнером.

Однако, тут заключена опасность. Иногда вы захотите удалить виджет из контейнера; может быть некоторый элемент вашего интерфейса является необязательным или появляется только при определенных обстоятельствах. Когда вы удаляете виджет (используя "gtk_container_remove()"), ссылка на него будет удалена, его счетчик ссылок упадет до 0, и он будет разрушен. Чтобы избежать этого, вы должны добавить ссылку на виджет перед его удалением. Список функций 3..9 приводит функции для манипулирования счетчиком ссылок.

Список функций 3..9: Учет ссылок
"#include "<gtk/gtkobject.h>
void gtk_object_ref(GtkObject *object) void gtk_object_unref(GtkObject *object) void gtk_object_sink(GtkObject *object)

"gtk_object_ref()" и "gtk_object_unref()" имеют варианты для виджетов ("gtk_widget_ref()", и т.д.), но версии для объектов и виджетов являются полными синонимами. Версии для виджетов остались от ранних версий Gtk+.

Итак, чтобы безопасно удалить виджет из контейнера, вы должны сделать следующее: gtk_widget_ref(widget); gtk_container_remove(container, widget);

Теперь виджет имеет одну ссылку, удерживаемую этим кодом. В некоторый момент вам нужно будет освободить ссылку, удаляя виджет. (Это будет иметь смысл сделать после повторного добавления виджета в какой-либо другой контейнер, например.)

Стоит напомнить, что удаление виджетов из контейнеров является особым случаем; в общем, быстрее будет просто спрятать виджет с помощью "gtk_widget_hide()", а затем вызвав "gtk_widget_show()", чтобы показать его потом.

"gtk_object_sink()" используется почти исключительно при реализации кода виджетов, когда вы, скорее всего, будете первичным владельцем объекта. Если объект не плавает, то "gtk_object_sink()" не произведет никакого эффекта. Чтобы заявить права на владение виджетом, проделайте следующее: gtk_object_ref(widget); gtk_object_sink(GTK_OBJECT(widget));

Этот код добавит ссылку на виджет; если виджет был плавающим, он также вычтет единицу из счетчика ссылок. Если виджет не был плавающим, "gtk_widget_sink()" не будет иметь эффекта.

Важно понять детали, потому что в некоторых случаях они могут играть свою роль. Но в основном, вы можете следовать нескольким простым правилам:


Linux Land
2000-09-15