wxPython before MainLoop
Chris Mellon
arkanes at gmail.com
Fri Aug 10 15:46:26 EDT 2007
On 8/9/07, Heikki Toivonen <heikki at osafoundation.org> wrote:
> [david] wrote:
> > I'd like to refresh the display before I start the main loop.
>
> We have this kind of situation in Chandler, where we display and update
> the splash screen before we enter MainLoop.
>
> 1. Create app object
> http://lxr.osafoundation.org/source/chandler/Chandler.py#080
>
> 2. During app object creation, in OnInit, put up splash screen and update it
>
> http://lxr.osafoundation.org/source/chandler/application/Application.py#433
>
> 3. The splash screen refresh is basically: draw new stuff,
> self.Layout(), self.Update(), wx.Yield()
> http://lxr.osafoundation.org/source/chandler/application/Application.py#1421
>
> 3. Start MainLoop
> http://lxr.osafoundation.org/source/chandler/Chandler.py#086
>
wxYield spins the event loop in place. This can have some serious
consequences if you aren't very careful with your usage, like
recursively entering event handlers. I generally consider it an
experts only interface, and avoid it.
Thankfully, in Python 2.5 you can do some very nice things with
Pythons generators. Basically, replace your wxYielding code with a
python generator that just yields where you used to wxYield, and then
call your generator repeatedly with wx.CallAfter.
Here's an (unpolished) example of a progress dialog that is updated
via generator:
import wx
def startupTask():
for ii in xrange(1001):
cont, skip = yield ii, "step %s"%str(ii)
if not cont:
raise StopIteration
class GeneratorProgress(wx.ProgressDialog):
""" Progress dialog fed via generator.
Task let should be a python generator that yields (value, message) tuples
and is sent (continue, skip) tuples, as per the arguments to and return
values from the wx.ProgressDialog.Update method.
"""
def __init__(self, title, message, tasklet, *args, **kwargs):
super(GeneratorProgress, self).__init__(title, message, *args, **kwargs)
self.tasklet = tasklet
wx.CallAfter(self.iterate)
def iterate(self, cont=None, skip=None):
try:
if cont is None and skip is None:
value, msg = self.tasklet.next()
else:
value, msg = self.tasklet.send((cont, skip))
cont, skip = self.Update(value, msg)
wx.CallAfter(self.iterate, cont, skip)
except StopIteration:
self.Destroy()
def main():
app = wx.App(False)
f = wx.Frame(None)
pg = GeneratorProgress("Startup", "running task...",
startupTask(), parent=f, maximum=1000)
pg.Show()
f.Show()
app.MainLoop()
if __name__ == '__main__':
main()
More information about the Python-list
mailing list