[wxPython-users] calling wx.CallAfter after wx.Frame.Destroy

Robin Dunn robin at alldunn.com
Mon Jan 21 17:37:15 PST 2008


Aaron Brady wrote:
>> -----Original Message-----
>> From: Robin Dunn [mailto:robin at alldunn.com]
>> Sent: Monday, January 21, 2008 12:20 PM
>>
>> Aaron Brady wrote:
>>> What if we call wx.CallAfter after calling frame.Destroy, where frame is
>> the
>>> only wx.Frame created?  I.e., does MainLoop return, after top-level
>> windows
>>> are destroyed, without the event queue being empty?
>> For top-level windows the Destroy method doesn't actually destroy the
>> window immediately, instead it is added to a pending delete queue which
>> is processed in idle time, which will happen after the pending events
>> are processed.
> 
> Will MainLoop exit if other events are added to the event queue after or
> during delete, or will it address those first?  IOW in other words, when
> does it return?

IIRC, it's a little different depending on how the platform specific 
event loops are handled, but in general when a TLW is finally destroyed 
wx checks if is was the last one in the top level window list, if so 
then it sets a flag that is checked in the next iteration of the main loop.

> 
> If one calls CallAfter while or after the pending delete queue is being
> processed, are further references are invalid?


The order of execution is essentially something like this pseudo-code:

while not exitFlag:
	while native events waiting:
		get next native event
		process native event
	
	process posted events
	send idle event
	delete destroyed TLWs


The wx.CallAfter's are implemented by posting events, so they are called 
before the pending delete queue is checked.  So yes it is possible that 
a TLW or widget used by a CallAfter function is not valid at the time 
the function is called, however if that was the last TLW and the main 
loop is exiting then it is probably not likely.  If in doubt it is easy 
to check.  When a C++ widget object is deleted and it knows what it's 
Python proxy object is, andif there is more than one reference to that 
proxy then wxPython will replace the __class__ of that proxy object with 
one that raises an exception if you try to evaluate any of it's 
attributes (the PyDeadObjectError exception) and it also has a 
__nonzero__ method that returns False.  That means that you can use a 
simple if test to see if the widget is still alive, like this:

	def MyCallAfterFunction(frame):
		if frame:
			frame.DoSomething()


-- 
Robin Dunn
Software Craftsman
http://wxPython.org  Java give you jitters?  Relax with wxPython!




More information about the wxpython-users mailing list