pygtk笔记本页面关闭内存泄漏

时间:2012-03-23 14:45:31

标签: python gtk pygtk

我有一个笔记本,其中包含带有标签的页面,其中包含关闭按钮。单击该按钮时,该选项卡中的页面将从笔记本中删除(已关闭)。 问题是当选项卡关闭时,内存永远不会被释放,因为似乎还有一些内容仍然引用了被破坏的页面。

以下是我笔记本的一些示例代码:

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回调,页面已成功从笔记本中删除,但内存永远不会被释放。

link概述了我遇到的同样问题。它建议的一件事是,通过自定义窗口小部件设置作为tab_label仍然有对页面的引用。我也尝试破坏自定义小部件,甚至递归地销毁它的所有子节点但仍然无法弄清楚仍在引用此页面的内容以将其保留在内存中。可能是什么问题?

4 个答案:

答案 0 :(得分:0)

在示例中唯一需要大量资源的是图像的pixbuf。尝试使用后明确销毁GtkImage。

答案 1 :(得分:0)

有趣的是,我上周在how to detect reference count issues in python上阅读了这篇博文。它可以帮助您找到谁保留参考。

答案 2 :(得分:0)

试试这个:

data.destory()
del data

然后等待python autogarbage集合(之后可能会工作几秒钟)

答案 3 :(得分:0)

我设法通过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()

这就是诀窍!在按钮

上调用destroy方法时,引用消失