【问题标题】:How to dispose GtkWidget's in Python, GTK3 and PyGObject?如何在 Python、GTK3 和 PyGObject 中配置 GtkWidget?
【发布时间】:2012-03-25 15:18:02
【问题描述】:

我正在为 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()

我希望当插件被禁用时,它添加到主机的所有小部件都应该被正确处理。

我发现这个问题非常相似:Free object/widget in GTK? 它提出了gtk_container_removegtk_widget_destroy。但我很担心:

  1. 考虑gtk_container_remove。它删除了宿主容器的直接子容器。就我而言,孩子也是许多其他小部件的组合,它们可能相互引用。删除直接子元素是否足以处理所有小部件?

  2. 考虑gtk_widget_destroy。它是递归的,似乎是我需要的,但也似乎太残酷了。手动销毁小部件真的有必要吗?将这项工作留给参考计数器会更好吗?

我愿意听听这个案例的“最佳实践”。

【问题讨论】:

    标签: python gtk3 pygobject


    【解决方案1】:

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

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

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

    【讨论】:

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

    从我的观点来看,你可以使用其中任何一个,因为会发生这样的事情:

    1. 当您使用gtk_container_remove时,如果您的子对象(self.guest)没有其他引用,那么它将被自动销毁。我的意思是 GtkContainer 会减少引用计数,然后 GObject 系统会调用 gtk_widget_destroy。
    2. 如果您调用 gtk_widget_destroy,那确实会销毁小部件,并在此过程中从其父级释放小部件。

    所以,你可以使用其中任何一个,但我会使用第一个。

    【讨论】:

      猜你喜欢
      • 2012-05-03
      • 2019-07-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多