local wx.Frame creation and garbage collector

32 views
Skip to first unread message

ericpell...@gmail.com

unread,
Nov 20, 2017, 1:59:29 PM11/20/17
to wxPython-users
Hi all,

I work on a wxPython application in which I bound the main frame to an wx.EVT_MENU. When the event is triggered the corresponding callback pops up a wx.Frame (I need it to be modeless).

Here is the code for the callback:

def on_open_my_frame(self, event):
    f
= MyFrame(self)
    f
.Show()



I am a bit surprised to see that this code works in the sense that the frame is opened and is functional. Indeed, I would expect troubles as the frame is 1) modeless 2) created locally which should trigger garbage collection and object destruction at the end of the scope. No ?


If so, does it mean that I must create my frame at the class level such as:


def on_open_my_frame(self, event):
   
if (getattr(self,"f",None) is not None):
       
self.f.Destroy()
   
self.f = MyFrame(self)
   
self.f.Show()
   

what do you think ?

Thx a lot

Eric

Tim Roberts

unread,
Nov 20, 2017, 2:13:43 PM11/20/17
to wxpytho...@googlegroups.com

I work on a wxPython application in which I bound the main frame to an wx.EVT_MENU. When the event is triggered the corresponding callback pops up a wx.Frame (I need it to be modeless).

Here is the code for the callback:

def on_open_my_frame(self, event):
    f
= MyFrame(self)
    f
.Show()

I am a bit surprised to see that this code works in the sense that the frame is opened and is functional. Indeed, I would expect troubles as the frame is 1) modeless 2) created locally which should trigger garbage collection and object destruction at the end of the scope. No ?


No.  In the wxWidgets code, the parent object ("self" in this case) gets its own reference to the new object.  That reference is not released until the parent window is destroyed.  Otherwise, perfectly useful code like yours above would explode.  It's quite common, for example, to create static text and button controls without keeping a local reference.



If so, does it mean that I must create my frame at the class level such as:

def on_open_my_frame(self, event):
   
if (getattr(self,"f",None) is not None):
       
self.f.Destroy()
   
self.f = MyFrame(self)
   
self.f.Show()
   

what do you think ?

You only need to do that if you need to refer to the dialog in other functions.  In the case of a dialog that gets reused, it's more common to create it once, then use Show and Hide to manage visibility.  What is the original code doing that you don't like?
-- 
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.

ericpell...@gmail.com

unread,
Nov 21, 2017, 3:39:04 AM11/21/17
to wxPython-users
Hi Tim,

I did not thought that from the wxwidgets side there is still the parent window that holds a reference to the newly created window (probably a shared_ptr I guess). Now it is completely clear.

In fact the life cycle of this dialog is really bound to this method (i.e. no need for it elsewhere) so now with your explanations in hand I am definitely ok to have implemented it like so.

Thanks a lot for the explanations.

Eric

Robin Dunn

unread,
Nov 21, 2017, 2:47:49 PM11/21/17
to wxPython-users
Also relevant here is that there are extra references to the Python object (aka the proxy object) used for tracking and other things. For example, whenever a wxWindow pointer is returned from a C++ method, and if that object was originally created in Python, then that original Python proxy object is located and returned.  There are also references to the proxy object held as part of the event bindings for methods of that class. And so on. Those extra references should all be properly cleaned up when the C++ object is destroyed, but it does mean that you can't reliably predict when the proxy object itself will be garbage collected. However due to those extra references it does mean that we don't need to hold on to the Python proxy objects for widgets in application code unless you need to access those objects later.

-- 
Robin Dunn
Software Craftsman
Reply all
Reply to author
Forward
0 new messages