I have a custom Gtk widget like MyWidget
defined in the code example below:
import gc
import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk
class MyWidget(Gtk.Button):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.x = 5
def __del__(self):
print('__del__ :', self, getattr(self, 'x', None))
def do_destroy(self):
print('do_destroy:', self, getattr(self, 'x', None))
# clean up self.x
widget = MyWidget()
del widget
gc.collect()
After the widget is destroyed, I need to do some cleanup (my custom widget is a button that opens a dialog window, after my button is destroyed, I would like to destroy the dialog window it created if it still exists, like FileChooserButton).
My problem is, running the code above, I get the output:
__del__ : <__main__.MyWidget object at 0x105340678 (__main__+MyWidget at 0x7fc1bc0bc340)> 5
do_destroy: <__main__.MyWidget object at 0x1053406c0 (__main__+MyWidget at 0x7fc1bc0bc340)> None
__del__ : <__main__.MyWidget object at 0x1053406c0 (__main__+MyWidget at 0x7fc1bc0bc340)> None
My understanding is that in PyGObject, all Python objects are just wrappers for the underlying GObject. So my reasoning for the above output is this. The widget
wrapper is about to be garbage collected so it's __del__()
method is called. After the widget
wrapper is garbage collected, it seems like the underlying widget is then prepared to be destroyed as the do_destroy()
method is then called. But do_destroy()
is called with self
set to a new wrapper object different to the original widget
object, and self.x
no longer exists. Then the new wrapper's __del__()
is called.
My question is, where should I put the 'self.x
clean up logic', and also if anyone knows, how does PyGObject create new wrapper objects (it does not seem to invoke __new__()
or __init__()
)?
Another problem with me putting the clean up logic in do_destroy()
is that do_destroy()
seems to be invoked every time the widget's destroy()
method is called, which can be done multiple times.