wxMessageBox with an auto-close timer in wxPython

imperialguy
imperialguy used Ask the Experts™
on
Platform and Python installation info:

Platforms: Windows, OS X
Python: Active State Python 2.7
wxPython: Version 2.9

Here is a sample code in which I use a wxMessageBox:

import wx,os

class Frame(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(100, 100),style=wx.MINIMIZE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN)
        
        host=os.system('hostname')
        if host!='superman':            
            self.dialogBox=wx.MessageBox('The host name should be superman. Closing this dialog box in 2s...','Info')            
            self.Destroy()
        else:
            self.Center()
            self.Show()
            
if __name__ == '__main__':
    app = wx.App(redirect=False)
    frame = Frame(None, -1, 'Sample')
    app.MainLoop()

Open in new window


According to the above piece of code, If the host name is not 'superman' , then the user is displayed a message box and prompted to press 'OK'. If the user presses 'OK' button on the message box, then the control moves to the next line in the code (i.e., line number 10) where the frame is destroyed. I want to be to able to automatically close the dialog box and go to the next line in the code i.e., self.Destroy() if the user does not press the 'OK' button in the next 2 seconds. Any thoughts on how do I do that in wxpython ?
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Firstly, it could be easier to get the computer name via os.getenv('COMPUTERNAME') in Windows and probably something similar in OS X.

Then, you probably want to show the main window before calling the MessageBox (i.e. put the self.Center() and self.Show() in front of it).

You need some timer and you need to bind it to some action.  The actions related to the GUI elements (the windows, buttons, etc.) are dispatched via internal messages of the windowing system.  This way you could generate a message that causes for example destruction of the window or to simulate the push action of a button.  The problem is that you have to send the message to the correct queue.  However, the MessageBox is intentionally very simple and you have no clean way to manipulate it from outside.  

You can bind the timer to the frame and you can do something; however, it is not that easy to self-destroy if the message box is open.  The reason is that the message box is a modal window, its events have the priority (its own message queue) and the frame cannot destroy its windows if the message box child still exists.  Try the following code that shows the problem:

import wx
import os

class MyFrame(wx.Frame):

    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(400, 300))

        # Create and set the timer for the frame.
        self.timer = wx.Timer(self)
        self.timer.Start(1000) # time interval in milisec
        self.Bind(wx.EVT_TIMER, self.onTimer, self.timer)

        # The counter for countdown.
        self.counter = 10 

        # Show the frame now; otherwise, the following MessageBox will prevent it.
        self.Center()
        self.Show(True)

        # Show the message box with static content.
        wx.MessageBox('The host name should be superman...', 'My title')               


    def onTimer(self, evt):
        '''The timer handler.'''
        self.counter -= 1
        self.SetLabel('Countdown %s...' % self.counter)
        if self.counter <= 0:
            self.timer.Stop()   # stop the timer
            self.Destroy()      # destroy the frame, but message box can prevent it!



class MyApplication(wx.App):

    def OnInit(self):
        wnd = MyFrame(None, wx.ID_ANY, 'Initial title')
        return True


def main():
    app = MyApplication()
    app.MainLoop()    


if __name__ == '__main__':
    main()

Open in new window


The conclusion is that you cannot use the MessageBox.  You have to use some not-so-simple window, and you have to bind the timer to that window (still, it can look the same as the message box).

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial