如何处置GtkWidget';在Python、GTK3和PyGObject中有什么?

如何处置GtkWidget';在Python、GTK3和PyGObject中有什么?,python,gtk3,pygobject,Python,Gtk3,Pygobject,我正在创建GTK3程序的插件。可以在运行时启用或禁用此插件。启用后,它应在宿主程序的给定区域(GtkBin)中填充其GUI。禁用时,它应将自身从该区域移除 此简单程序描述了以下用法: #!/usr/bin/python2 from gi.repository import Gtk window = Gtk.Window() class Plugin(object): def __init__(self, host): assert(isinstance(host,

我正在创建GTK3程序的插件。可以在运行时启用或禁用此插件。启用后,它应在宿主程序的给定区域(GtkBin)中填充其GUI。禁用时,它应将自身从该区域移除

此简单程序描述了以下用法:

#!/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\u container\u remove
gtk\u widget\u destroy
。但我担心:

  • 考虑删除
    gtk\u容器
    。它删除主机容器的直接子级。在我的例子中,孩子也是许多其他小部件的组合,它们可能相互引用。删除直接子项是否足以处理所有小部件

  • 考虑
    gtk\u widget\u destroy
    。它是递归的,似乎是我需要的,但也似乎太残酷了。手动销毁小部件真的需要这样做吗?把那份工作交给推荐人会更好吗


  • 我愿意听到关于这种情况的“最佳实践”。

    最佳实践是永远不要依赖垃圾收集器来及时收集控制有限资源的对象。它可能会无限期地延迟收集任何特定的垃圾。您不想让垃圾收集器清理文件,因为一次可以打开的文件句柄数量是有限制的

    Python的垃圾收集器有一个引用计数器,可以立即释放没有引用的对象,但这是一个实现细节。如果您使用另一个实现,例如PyPy或IronPython,则这不适用。当我将程序迁移到另一个实现时,我遇到了程序中断,因为我无意中依赖Python的引用计数来清理资源。此外,您可能会因为意外地在某个地方创建了一个循环而导致出现错误


    我不知道有什么专门针对小部件的最佳实践。我没有考虑我应该清理这些东西的可能性。如果一个小部件有一个与之相关联的窗口,理论上你应该清理这个操作系统句柄。通常,只有GtkWindow才会有一个真正的窗口,但是您的插件可以创建一个带有窗口的小部件。所以,我想说,在一个特定的不太可能的情况下,理论上应该销毁这个小部件。否则,如果您不需要它们,可以手动销毁它们,但我要说的是,不要特意这么做。

    从我的观点来看,您可以使用其中任何一种,因为将发生的情况是:

  • 当您使用gtk\u container\u remove时,如果您的子对象(self.guest)没有其他引用,那么它将自动销毁。我的意思是GtkContainer将减少引用计数,GObject系统将调用gtk\u widget\u destroy
  • 如果您调用gtk_widget_destroy,则确实会销毁该小部件,并在此过程中从其父级释放该小部件

  • 因此,您可以使用其中任何一种,但我将使用第一种。

    理解为什么不依赖GC回收内存以外的资源需要相当长的时间。我最初的问题暗示了一种“所有权”关系,窗口拥有它的子窗口。Qt中
    QObject
    的析构函数就是一个很好的例子。