страница ноутбука pygtk закрыть утечка памяти - PullRequest
1 голос
/ 23 марта 2012

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

Вот пример кода для моего ноутбука:

notebook = gtk.Notebook
def create_tab():
    page = gtk.Label( "THis is a page")
    page.show()
    tab = gtk.HBox()#The custom tab-label widget
    tab_label = gtk.Label( "Tab")
    tab_label.show()
    tab.pack_start( tab_label)
    tab_close = gtk.Button()
    tab_close.set_image(gtk.image_new_from_stock(gtk.STOCK_CLOSE, gtk.ICON_SIZE_MENU))
    tab_close.connect( 'clicked', destroy_tab, page )
    tab_close.show()
    tab.pack_end( tab_close)
    tab.show()

    notebook.append_page(page, tab)
def destroy_tab( widget, data=None):
    page_num = notebook.page_num( data )
    notebook.remove_page( page_num )
    data.destroy()

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

Эта ссылка описывает ту же проблему, что и я. И одна вещь, которую он предлагает, - это то, что все еще есть ссылка на страницу через пользовательский виджет, установленный как tab_label. Я также пытался уничтожить пользовательский виджет, даже рекурсивно уничтожая все его дочерние элементы, но до сих пор не могу понять, что все еще ссылается на эту страницу, чтобы сохранить ее в памяти. В чем может быть проблема?

Ответы [ 4 ]

0 голосов
/ 18 апреля 2012

Мне удалось выяснить, через gc.getreferrers(), что была круговая ссылка между кнопкой закрытия и страницей, которую он закрывал. В ходе дальнейшего тестирования я обнаружил, что это не моя вина, но способ, которым GtkNotebook связывает их, когда они добавляются в ноутбук. Мне удалось избавиться от этой круговой ссылки просто путем создания пользовательской кнопки, которая содержит ссылку на сам виджет, и затем, когда кнопка уничтожается, эта ссылка на виджет устанавливается на None, и это, кажется, успешно избавляется от ссылки. Тем не менее, это все еще не очищает память за страницей после ее закрытия.

Вот обновленный код:

class CloseButton(gtk.Button):
    def __init__(self, widget):
        gtk.Button.__init__(self)
        self.widget_ref = widget#Pass the widget reference to this button
        #Initialize the button here...
        self.connect( 'destroy', self.on_destroy )
    def on_destroy( self, widget ):
        self.widget_ref = None#Destroy the reference to the widget

И тогда в коде вы бы использовали кнопку так:

notebook = gtk.Notebook
def create_tab():
    page = gtk.Label( "THis is a page")
    page.show()
    tab = gtk.HBox()#The custom tab-label widget
    tab_label = gtk.Label( "Tab")
    tab_label.show()
    tab.pack_start( tab_label)
    tab_close = CloseButton(page)#pass a reference to page

    tab_close.connect( 'clicked', destroy_tab )
    tab_close.show()
    tab.pack_end( tab_close)
    tab.show()

    notebook.append_page(page, tab)

def destroy_tab( widget, data=None):
    page_num = notebook.page_num( widget.widget_ref )
    notebook.remove_page( page_num )
    widget.destroy()

И это делает трюк! Ссылка исчезает при вызове метода уничтожения на кнопке

0 голосов
/ 11 апреля 2012

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

0 голосов
/ 18 апреля 2012

попробуйте это:

data.destory()
del data

затем дождитесь автоматической сборки мусора на python (может сработать через несколько секунд)

0 голосов
/ 04 апреля 2012

Единственной вещью, которая требует значительных ресурсов в примере, является pixbuf изображения. Попробуйте явно уничтожить GtkImage после его использования.

...