2012-03-25 6 views
4

Ich erstelle ein Plug-in für ein GTK3-Programm. Dieses Plug-in kann zur Laufzeit aktiviert oder deaktiviert werden. Wenn es aktiviert ist, sollte es die GUI in einem bestimmten Bereich (einem GtkBin) im Host-Programm auffüllen. Wenn es deaktiviert ist, sollte es sich aus diesem Bereich entfernen.Wie GtkWidget in Python, GTK3 und PyGObject zu entsorgen?

Dieses einfache Programm stellt die Nutzung:

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

Ich wünsche, dass, wenn die Plug-in deaktiviert ist, alle Widgets es den Host hinzugefügt sollte ordnungsgemäß entsorgt werden.

Ich habe diese Frage ziemlich ähnlich: Free object/widget in GTK? Es wurde vorgeschlagen, gtk_container_remove und gtk_widget_destroy. Aber ich mache mir Sorgen:

  1. Betrachten gtk_container_remove. Es entfernt das direkte Kind des Host-Containers. In meinem Fall ist das Kind auch eine Zusammensetzung von vielen anderen Widgets und sie können sich gegenseitig referenzieren. Wird das direkte Kind genug entfernen, damit alle Widgets entsorgt werden können?

  2. Betrachten gtk_widget_destroy. Es ist rekursiv und scheint zu sein, was ich brauche, scheint aber auch zu brutal. Ist das wirklich notwendig, um ein Widget manuell zu zerstören? Wäre es besser, diesen Job dem Referenzzähler zu überlassen?

Ich bin bereit, die "Best Practice" für diesen Fall zu hören.

Antwort

2

Bewährte Methode ist, sich niemals auf einen Garbage Collector zu verlassen, um ein Objekt zu sammeln, das eine begrenzte Ressource zeitnah steuert. Es könnte den unbegrenzten Einzug bestimmter Abfälle verzögern. Sie sollten nicht zulassen, dass eine Datei für den Garbage Collector geöffnet bleibt, da die Anzahl der Dateihandles, die Sie gleichzeitig geöffnet haben können, begrenzt ist.

Es passiert, dass Pythons Garbage Collector einen Referenzzähler hat und Objekte ohne Referenzen sofort freigibt, aber das ist ein Implementierungsdetail. Wenn Sie eine andere Implementierung wie PyPy oder IronPython verwenden, gilt dies nicht. Ich hatte eine Programmunterbrechung, als ich sie in eine andere Implementierung verschoben habe, weil ich mich unbeabsichtigt auf Pythons Referenzzählung verlassen hatte, um Ressourcen zu bereinigen. Außerdem können Fehler auftreten, weil Sie versehentlich irgendwo einen Zyklus erstellt haben.

Ich kenne keine Best Practices für Widgets speziell. Ich hatte nicht die Möglichkeit in Betracht gezogen, dass ich diese aufräumen sollte. Wenn einem Widget ein Fenster zugeordnet ist, handelt es sich um eine Betriebssystemkennung, die Sie theoretisch bereinigen sollten. Normalerweise hat nur ein GtkWindow ein echtes Fenster, aber es ist möglich, dass Ihr Plugin ein Widget mit einem Fenster erstellt. Ich würde also sagen, dass Sie in diesem speziellen Fall das Widget theoretisch zerstören sollten. Ansonsten ist es in Ordnung, sie manuell zu zerstören, wenn Sie sie nicht brauchen, aber ich würde sagen, tun Sie nicht alles, um dies zu tun.

+0

Es dauert ziemlich lange, um zu verstehen, warum man sich nicht auf GC verlässt, um andere Ressourcen als Speicher wiederzugewinnen. Meine ursprüngliche Frage impliziert eine Art "Eigentums" -Beziehung, in der das Fenster seine Kinder besitzt. Der Destruktor von 'QObject' in Qt ist ein gutes Beispiel. – wks

1

Meiner können Sie alle diejenigen verwenden, da das, was Wille geschieht, ist dies:

  1. Wenn Sie gtk_container_remove, wenn Ihr Kind Objekt (self.guest) haben keine andere Referenz, dann wird automatisch zerstört. Ich meine GtkContainer wird die Referenzzahl verringern und das GObject System wird dann gtk_widget_destroy aufrufen.
  2. Wenn Sie gtk_widget_destroy aufrufen, wird das in der Tat das Widget zu zerstören, und dabei wird das Widget von seinem Elternteil freigegeben.

So können Sie alle von denen verwenden, aber ich werde die erste verwenden.