[wxPython-users] Re: wxProgressDialog problems

Robin Dunn robin at alldunn.com
Tue Feb 26 13:13:40 PST 2008


Larry Bates wrote:

> =

> I appreciate your attempts to help me but I'm still dead-in-the-water.  =

> For some reason the MailLoop does NOT exit immediately (even without =

> app.SetExitOnFrameDelete(False)).  The messages that I post via =

> wx.PostEvent in my (non-GUI) loop DO get processed properly and the GUI =

> dialog including the title, message1 and gauge are all updated as =

> expected, but I can't click on the Cancel button (hourglass cursor =

> whenever I hover over the dialog and clicks do nothing).  This is =

> soooo... close, that its frustrating.

I've made a somewhat simpler example that illustrates what I've been =

trying to say.  It creates a new thread for initializing and running wx, =

so this will be the gui thread and you can continue to do your other =

stuff in the main thread.  I then created a simple proxy of =

wx.ProgressDialog that uses wx.CallAfter to cause the real UI methods to =

be called in the context of the gui thread, and it also uses a =

threading.Event to cause one of the proxy methods to wait until the real =

method has completed in the gui thread so the result can be returned to =

the non-gui thread.  (If you don't want to wait then there are other =

ways do handle it, such as using a callback, etc.)

I created a hidden frame because I was having troubles getting =

SetExitOnFrameDelete to work as I was expecting.  I think there is a bug =

there that I'll track down, but in the meantime the hidden frame works =

just as well to keep the wx MainLoop alive.


-- =

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

-------------- next part --------------

import threading
import time

import wx
print wx.version()


class WxThread(threading.Thread):
    def run(self):
        self.app =3D wx.App(redirect=3DFalse)
        #app.SetExitOnFrameDelete(False)
        hiddenFrame =3D wx.Frame(None)
        self.app.MainLoop()

    def ExitMainLoop(self):
        wx.CallAfter(self.app.ExitMainLoop)
        =

    def start(self):
        threading.Thread.start(self)
        time.sleep(0.1)  # give wx a chance to get started before returning
        =


class ThreadSafeProgressDialog(object):
    def __init__(self):
        self.dlg =3D None
        self.keepGoing =3D True
        self.updateEvt =3D threading.Event()
        =

    def Create(self, title, message, maximum=3D100, parent=3DNone, style=3D=
wx.PD_AUTO_HIDE|wx.PD_APP_MODAL):
        wx.CallAfter(self._Create, title, message, maximum, parent, style)

    def _Create(self, *args, **kw):
        self.dlg =3D wx.ProgressDialog(*args, **kw)
        =

    def Show(self):
        wx.CallAfter(self._Show)

    def _Show(self):
        self.dlg.Show()

    def Update(self, value, newmsg=3D""):
        self.updateEvt.clear()
        wx.CallAfter(self._Update, value, newmsg)
        self.updateEvt.wait()
        return self.keepGoing

    def _Update(self, value, newmsg):
        self.keepGoing, skip =3D self.dlg.Update(value, newmsg)
        self.updateEvt.set()
    =

    def Destroy(self):
        wx.CallAfter(self.dlg.Destroy)
        =



# start wx in a thread
wxt =3D WxThread()
wxt.start()

# do some stuff in the main thread that needs progress dialogs
for f in ['one', 'two', 'three']:
    tspd =3D ThreadSafeProgressDialog()
    tspd.Create('File upload', 'file: %s' % f,
                style=3Dwx.PD_APP_MODAL |
                wx.PD_AUTO_HIDE | =

                wx.PD_CAN_ABORT | =

                wx.PD_REMAINING_TIME)
    tspd.Show()
    for pct in range(100):
        time.sleep(0.1)
        if not tspd.Update(pct):
            break
    tspd.Destroy()

# tell wx to exit the main loop, which will then exit the gui thread
wxt.ExitMainLoop()



More information about the wxpython-users mailing list