简体   繁体   English

如何在Python,GTK3和PyGObject中部署GtkWidget?

[英]How to dispose GtkWidget's in Python, GTK3 and PyGObject?

I am creating a plug-in to a GTK3 program. 我正在为GTK3程序创建一个插件。 This plug-in can be enabled or disabled at runtime. 可以在运行时启用或禁用此插件。 When enabled, it should populate its GUI in a given area (a GtkBin) in the host program. 启用后,它应在主程序中的给定区域(GtkBin)中填充其GUI。 When disabled, it should remove itself from that area. 禁用时,它应该从该区域中删除。

This simple program depicts the usage: 这个简单的程序描述了用法:

#!/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()

I wish that when the plug-in is disabled, all widgets it added to the host should be properly disposed. 我希望在禁用插件时,应该正确处理它添加到主机的所有小部件。

I have found this question quite similar: Free object/widget in GTK? 我发现这个问题非常相似: GTK中的免费对象/小部件? It proposed gtk_container_remove and gtk_widget_destroy . 它提出了gtk_container_removegtk_widget_destroy But I am worrying: 但我担心的是:

  1. Consider gtk_container_remove . 考虑gtk_container_remove It removes the direct child of the host container. 它删除了主机容器的直接子节点。 In my case, the child is also a composition of many other widgets and they may be referencing each other. 就我而言,孩子也是许多其他小部件的组合,他们可能互相引用。 Will removing the direct child enough for all the widgets to be disposed? 是否会删除直接的孩子,以便处理所有小部件?

  2. Consider gtk_widget_destroy . 考虑gtk_widget_destroy It is recursive and appears to be what I need, but also seems too brutal. 它是递归的,似乎是我需要的,但也似乎太残酷了。 Is this really necessary to manually destroy a widget? 这是否真的需要手动销毁小部件? Would it be better to leave that job to the reference-counter? 将这份工作留给参考柜台会更好吗?

I am willing to hear the "best practice" for this case. 我愿意听到这个案子的“最佳做法”。

Best practice is to never rely on a garbage collector to collect an object that controls a limited resource in a timely fashion. 最佳做法是永远不要依赖垃圾收集器来收集及时控制有限资源的对象。 It could delay collecting any particular garbage indefinitely. 它可以无限期地延迟收集任何特定的垃圾。 You wouldn't want to leave a file open for the garbage collector to clean up, because there's a limit to the number of file handles you can have open at once. 您不希望为垃圾收集器打开文件以进行清理,因为您可以立即打开的文件句柄数量有限制。

It happens that Python's garbage collector has a reference counter and will free objects with no references immediately, but that is an implementation detail. 碰巧Python的垃圾收集器有一个引用计数器,并且会立即释放没有引用的对象,但这是一个实现细节。 If you use another implementation, such as PyPy or IronPython, this does not apply. 如果您使用其他实现,例如PyPy或IronPython,则不适用。 I've had a program break when I moved it to another implementation, because I had inadvertently relied on Python's reference counting to clean up resources. 当我将它移动到另一个实现时,我有一个程序中断,因为我无意中依赖Python的引用计数来清理资源。 Also, you can end up with bugs that happen because you accidentally create a cycle somewhere. 此外,您最终可能会因为意外在某处创建循环而发生错误。

I don't know of any best practices for widgets specifically. 我不知道具体的小部件的任何最佳实践。 I hadn't considered the possibility that I should be cleaning those up. 我没有考虑过我应该清理它们的可能性。 If a widget has a window associated with it, that is an OS handle that you should theoretically clean up. 如果一个小部件有一个与之关联的窗口,那么理论上应该清理一个OS句柄。 Usually, only a GtkWindow will have a real window, but it's possible for your plugin to create a widget with a window. 通常,只有GtkWindow会有一个真实的窗口,但是你的插件可能会创建一个带窗口的窗口小部件。 So, I would say that in that one specific unlikely case, you should theoretically destroy the widget. 所以,我会说,在一个特定的不太可能的情况下,你理论上应该销毁小部件。 Otherwise, it's fine to destroy them manually if you don't need them, but I would say don't go out of your way to do so. 否则,如果你不需要它们,可以手动销毁它们,但我会说不要这么做。

From my point you can use any of those, since what will happens is this: 从我的观点来看,你可以使用其中任何一种,因为会发生的是:

  1. When you use gtk_container_remove , if your child object (self.guest) have no other reference, then it will be destroyed automatically. 当您使用gtk_container_remove时 ,如果您的子对象(self.guest)没有其他引用,那么它将被自动销毁。 I mean GtkContainer will decrease the reference count and the GObject system will call then gtk_widget_destroy. 我的意思是GtkContainer将减少引用计数, GObject系统将调用gtk_widget_destroy。
  2. If you call gtk_widget_destroy , the that will indeed destroy the widget, and in the process will release the widget from its parent. 如果你调用gtk_widget_destroy ,那确实会破坏小部件,并且在此过程中将从其父级释放小部件。

So, you can use any of those, but I will use the first one. 所以,你可以使用其中任何一个,但我将使用第一个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM