Как избавиться от GtkWidget в Python, GTK3 и PyGObject? - PullRequest
4 голосов
/ 25 марта 2012

Я создаю плагин для программы GTK3. Этот плагин может быть включен или отключен во время выполнения. Когда он включен, он должен заполнять свой GUI в заданной области (GtkBin) в программе хоста. При отключении он должен удалить себя из этой области.

Эта простая программа описывает использование:

#!/usr/bin/python2

from gi.repository import Gtk

window = Gtk.Window()

class Plugin(object):
    def __init__(self, host):
        assert(isinstance(host, Gtk.Bin))
        self.host = host
        self.guest = None

    def enable(self):
        box = Gtk.Box(orientation = Gtk.Orientation.VERTICAL)
        for x in range(10):
            box.add(Gtk.Button("Button {}".format(x)))

        self.guest = box
        self.host.add(self.guest)

    def disable(self):
        self.host.remove(self.guest)
        # self.guest.destroy() # is this better?
        self.guest = None

plugin = Plugin(window)

plugin.enable()
#plugin.disable()

window.connect("destroy", Gtk.main_quit)
window.show_all()

Gtk.main()

Мне бы хотелось, чтобы, когда плагин отключен, все виджеты, добавленные на хост, были правильно расположены.

Я нашел этот вопрос довольно похожим: Свободный объект / виджет в GTK? Предложено gtk_container_remove и gtk_widget_destroy. Но я волнуюсь:

  1. Рассмотрим gtk_container_remove. Удаляет прямой дочерний элемент хост-контейнера. В моем случае дочерний элемент также является композицией многих других виджетов, и они могут ссылаться друг на друга. Хватит ли удаления прямого потомка для удаления всех виджетов?

  2. Рассмотрим gtk_widget_destroy. Это рекурсивно и кажется тем, что мне нужно, но также кажется слишком жестоким. Это действительно необходимо, чтобы вручную уничтожить виджет? Было бы лучше оставить эту работу на счетчик ссылок?

Я готов услышать «лучшую практику» для этого случая.

Ответы [ 2 ]

2 голосов
/ 26 марта 2012

Лучше всего никогда не полагаться на сборщик мусора для своевременного сбора объекта, который контролирует ограниченный ресурс.Это может задержать сбор любого конкретного мусора на неопределенный срок.Вы не хотели бы оставлять файл открытым для очистки сборщика мусора, потому что существует ограничение на количество дескрипторов файлов, которые вы можете открыть одновременно.

Бывает, что сборщик мусора Python имеет ссылкуСчетчик и немедленно освободит объекты без ссылок, но это деталь реализации.Если вы используете другую реализацию, такую ​​как PyPy или IronPython, это не применяется.У меня был программный перерыв, когда я переместил его в другую реализацию, потому что я непреднамеренно полагался на подсчет ссылок Python для очистки ресурсов.Кроме того, вы можете столкнуться с ошибками, которые происходят из-за того, что вы случайно создали где-то цикл.

Я не знаю каких-либо лучших практик для виджетов.Я не думал о том, что мне следует их убирать.Если с виджетом связано окно, то это дескриптор ОС, который вы должны теоретически очистить.Обычно реальное окно имеет только GtkWindow, но ваш плагин может создать виджет с окном.Итак, я бы сказал, что в этом конкретном маловероятном случае вы должны теоретически уничтожить виджет.В противном случае, можно уничтожить их вручную, если они вам не нужны, но я бы сказал, не пытайтесь это сделать.

1 голос
/ 26 марта 2012

С моей точки зрения, вы можете использовать любой из них, поскольку то, что произойдет, это:

  1. Когда вы используете gtk_container_remove , если ваш дочерний объект (self.guest) не имеет другой ссылки, он будет уничтожен автоматически. Я имею в виду GtkContainer уменьшит счетчик ссылок, и система GObject вызовет gtk_widget_destroy.
  2. Если вы вызовете gtk_widget_destroy , это действительно уничтожит виджет, и в процессе освободит виджет от его родителя.

Итак, вы можете использовать любой из них, но я буду использовать первый.

...