Auto-pulsing wxProgressDialog?

This is a general concurrency problem. Your application is not
multithreaded, and it is blocking execution of everything else while
it is running (you won't be able to interact with your application,
either).

There are a number of ways to work around this. The most common is to
run your worker function from a secondary thread, having it post an
event back to the main thread (using wx.CallAfter) when it is
completed. In response to this "completed" thread, your application
can destroy the progress dialog and continue processing.

Recent version of wxPython include a library called
wx.lib.delayedresult which can help with this, it is featured in the
demo under the process and events category.

···

On 1/3/07, Rooney, Mike (ext. 324) <mxr@qvii.com> wrote:

Hello everyone. I am looking for a progress dialog that basically just moves along and starts over again until it is told to stop or destroy. I have seen these in Windows and other places all the time however not in wx. Normally I hate progress dialogs that don't actually show progress, however for our current application a call is made to a module that could take awhile and we have no way of getting actual progress, but I want the user to know the program hasn't frozen.

I have tried using a wxTimer which calls Pulse() on the ProgressDialog every 100 milliseconds, however that didn't do anything while the function call was running, defeating the entire purpose. I also tried making a little class that Pulses the dialog and running that in a thread, which also didn't work. Maybe the function call is taking up all the CPU and that is why the timer and thread didn't work? I once had the function call crash and then the dialog pulsed along as I would expect, so that seems to tell me what I am doing is right but it isn't getting enough priority. This is why I thought if there was a built-in way to do this in wx it might solve the problem.

Does anyone have any ideas as to how to solve this issue?

Call Refresh() after Pulse().

···

On 1/3/07, Rooney, Mike (ext. 324) <mxr@qvii.com> wrote:

>Recent version of wxPython include a library called
>wx.lib.delayedresult which can help with this, it is featured in the
>demo under the process and events category.

I gave it a shot but the same thing happens. I just don't understand!
I replaced the database call with a sleep call just to simplify even
more but still no pulsing occurs.

Let me post a little code and maybe it will be clear what I am doing
wrong. onPack in the controller is what is called first. It tells the
view to show the dialog, which is supposed to start a timer but it
never pulses and 12 never gets printed.

in the controller:
    def onPack(self, event=None):
                self.view.showPackDialog()

            import time, wx.lib.delayedresult as delayedresult
            delayedresult.startWorker(self.onPackDone, lambda:time.sleep(5))

    def onPackDone(self, result):
                self.view.closePackDialog()

in the view:
    def showPackDialog(self):
        self.dlg = wx.ProgressDialog("Packing Database", "Packing routines in the ZopeDB", parent=self)
        self.t = wx.Timer(self)
        self.t.Bind(wx.EVT_TIMER, self.onPackTimer)
        self.t.Start(10)

    def onPackTimer(self, e):
        print 12 #debug
        self.dlg.Pulse()

    def closePackDialog(self):
        self.t.Stop()
        self.dlg.Destroy()

Thanks for your help so far, it is greatly appreciated. Hopefully the
code is clean and easy to interpret (no pun intended).

Call Refresh() after Pulse().

Your previous fix was all that was necessary, thanks! What a tiny error.
What actually happens when I bound it to the timer itself, is that valid?
And if not why doesn't wx complain?

If it is working fine should I add the call to Refresh or leave it as it is?
Thanks again!