Search code examples
pythonwxpython

How can I get the ProgressDialog to close before I open my MessageBox?


I've made a runnable example that demonstrates the buggy behavior: http://pastebin.com/8KpzD4pw


This issue is EXTREMELY aggravating. I have a wx.ProgressDialog up while I'm saving a file, and upon IOError, I want to close the progress dialog and display an error message. Unfortunately, this seems to be impossible. The progress dialog blatantly refuses to close before the message box closes:

Illustration

As you can see, the message box appears below the progress dialog, so the user has to manually switch focus to the message box to see it's contents. When the message box is closed, the progress dialog disappears as well. Here is the code for the save function:

def save(self, path=None):
    # Show a loading dialog while the document is staving.
    progress = shared.show_loading(self, 'Saving document')

    try:
        raise IOError('Error message')

        if not path:
            self.document.save()
        else:
            self.document.save_to_file(path)
    except IOError as e:
        progress.done()

        message = 'Failed to save file:\n\n{}'.format(e.message)
        wx.MessageBox(message, 'Error', wx.OK | wx.ICON_ERROR)

    progress.done()

The show_loading and progress.done functions are just shortcuts for using the wx.ProgressDialog (source).

Why does the progress dialog not disappear before the message box is opened? How can I fix it?


I have also tried using wx.CallAfter to open the message box, to no avail:

# ...
except IOError as e:
    message = 'Failed to save file:\n\n{}'.format(e.message)

    def show_error():
        wx.MessageBox(message, 'Error', wx.OK | wx.ICON_ERROR)

    progress.done()
    wx.CallAfter(show_error)
# ...

I have also tried to sleep for 100ms between closing the progress dialog and opening the message box using wx.MicroSleep without success.

I have also tried calling wx.Yield() and wx.WakeUpIdle() right after destroying the progress dialog, neither having any effect.


Solution

  • I had a similar case, which I finally resolved by calling:

    dlg.Update( dlg.GetRange( ) )
    

    It seems that, at least when you put the progress dialog into "pulse" mode, it won't immediately respond to Destroy calls. No amount of sleeping or yielding before or after destroying it would convince my progress dialog to stop displaying. However, by instead simply updating the value to the max, it seems to automatically destroy (or at least hide) itself immediately.