Understanding wx.Yield()

3,763 views
Skip to first unread message

rocketman

unread,
Apr 9, 2011, 8:33:49 PM4/9/11
to wxpytho...@googlegroups.com
I have a general question with what is going on with a wx.Yield() call.

I am developing a transparent static text widget. I have extended
wx.StaticText and have bound EVT_PAINT to my paint() method. Things work
great ... when I call SetLabel() ... my custom paint() method gets called
and provides the painting behavior that I desire to create the effect of
transparency.

It was working fine until I started placing an additional amount of long
running code immediately following the SetLabel() call - and in this case I
get the old paint behavior. I did a little research and tried a wx.Yield()
immediately following the SetLabel() call ... and now it is working again.

My question is ... what is actually going on here? The best I can figure is
that my python code is running with the GIL in place ... such that when
wxWidgets tries to execute my paint() method it cannot get access to it ...
so rather than waiting ... it then moves up the event hierarchy (as if I had
called Skip()) and executes the default paint behavior for this class. Must
be the Yield() call allows my paint() code to be called?

Is this interpretation correct?

--
View this message in context: http://wxpython-users.1045709.n5.nabble.com/Understanding-wx-Yield-tp4293704p4293704.html
Sent from the wxPython-users mailing list archive at Nabble.com.

Micah Nordland

unread,
Apr 9, 2011, 9:51:40 PM4/9/11
to wxpytho...@googlegroups.com
To my knowledge, wx.Yield creates a nested event loop, but as to knowing what a nested event loop is, other than that it is like wx.App inside another wx.App
--
Hi, I will kill all ads in google gmail.
They will all be dead and gone for all my emails to you. HA HA bye bye ads I just massacred you!!!

Robin Dunn

unread,
Apr 11, 2011, 4:05:49 PM4/11/11
to wxpytho...@googlegroups.com
On 4/9/11 5:33 PM, rocketman wrote:
> I have a general question with what is going on with a wx.Yield() call.
>
> I am developing a transparent static text widget. I have extended
> wx.StaticText and have bound EVT_PAINT to my paint() method. Things work
> great ... when I call SetLabel() ... my custom paint() method gets called
> and provides the painting behavior that I desire to create the effect of
> transparency.
>
> It was working fine until I started placing an additional amount of long
> running code immediately following the SetLabel() call - and in this case I
> get the old paint behavior. I did a little research and tried a wx.Yield()
> immediately following the SetLabel() call ... and now it is working again.
>
> My question is ... what is actually going on here? The best I can figure is
> that my python code is running with the GIL in place ... such that when
> wxWidgets tries to execute my paint() method it cannot get access to it ...
> so rather than waiting ... it then moves up the event hierarchy (as if I had
> called Skip()) and executes the default paint behavior for this class. Must
> be the Yield() call allows my paint() code to be called?
>
> Is this interpretation correct?

No. As Micah mentioned the various yield functions are essentially a
nested event loop that reads and dispatches pending events from the
event queue. When the queue is empty then the yield function returns.

The reason this fixes the problem you are seeing is that your long
running tasks are preventing control from returning to the main event
loop and so the paint event for your custom widget will just sit in the
queue until the long running task completes and control is allowed to
return to the main loop. Adding the yield allows those events to be
processed sooner, but you may still have problems when the long running
task does finally run because any new events that need to be processed
during that time (for example, the user clicks a Cancel button) will
still have to wait until the LRT is finished.

Another issue to watch out for when using a yield function is that it
could lead to an unexpected recursion. For example you have a LRT that
periodically calls yield so events can be processed, but one of the
events that happens is one whose event handler starts the LRT again.

So usually it is better to use some other way to prevent blocking of
events while running a the LRT, such as breaking it up into chunks that
are run from EVT_IDLE handlers, or using a thread. See

http://wiki.wxpython.org/LongRunningTasks
http://wiki.wxpython.org/Non-Blocking_Gui

--
Robin Dunn
Software Craftsman
http://wxPython.org

rocketman

unread,
Apr 13, 2011, 5:05:48 PM4/13/11
to wxpytho...@googlegroups.com
Thanks Robin. As always your explanation and references were very useful as
I was able quickly get to the bottom of this.

--
View this message in context: http://wxpython-users.1045709.n5.nabble.com/Understanding-wx-Yield-tp4293704p4301646.html

Reply all
Reply to author
Forward
0 new messages