Search code examples
wxpythonwxwidgets

wxpython-can we add ok button on pybusyinfo dialog?


I have created pybusyinfo dialog to display message and after 30 secs of sleep it will automatically close.

Now i need to add ok button in that dialog to get user input and they are not pressed the button the dialog should close in 30secs.

Can we add that button into wx.lib.agw.pybusyinfo dialog ?

Or is there any other dialog of wx widgets will automatically close after sometime?

import wx
import wx.lib.agw.pybusyinfo as PBI
retVal = showmsg("dialog will be closed in 30 secs...")
time.sleep(30)
retVal = None

def showmsg(msg):
    app = wx.App(redirect=False)
    title = 'Message!'
    retVal = PBI.PyBusyInfo(msg, title=title)
    return retVal

Solution

  • Write your own busy dialog which contains a gauge to show that it is busy.
    Use a wxTimer to loop the guage.
    This should get you started:

    import wx
    class MyFrame(wx.Frame):
        def __init__(self, parent):
            wx.Frame.__init__(self, parent, -1, "Busy Dialog",size=(500,200))
            self.panel = wx.Panel(self)
            sizer = wx.BoxSizer(wx.VERTICAL)
            self.log = wx.TextCtrl(self.panel, wx.ID_ANY, size=(400,100),style = wx.TE_MULTILINE|wx.TE_READONLY|wx.VSCROLL)
            self.button = wx.Button(self.panel, label="Click me")
            sizer.Add(self.log, 0, wx.EXPAND | wx.ALL, 10)
            sizer.Add(self.button, 0, wx.EXPAND | wx.ALL, 10)
            self.panel.SetSizer(sizer)
            self.Bind(wx.EVT_BUTTON, self.OnButton)
    
        def OnButton(self,event):
            dlg = Busy(parent = self.panel) 
            dlg.ShowModal()
            if dlg.result_text:
                self.log.AppendText("Text Input: "+dlg.result_text+"\n")
            dlg.Destroy()
    
    class Busy(wx.Dialog):
        def __init__(self, parent):
            wx.Dialog.__init__(self, parent, wx.ID_ANY, "Busy", size= (420,240))
            self.panel = wx.Panel(self,wx.ID_ANY)
            self.label = wx.StaticText(self.panel, label="Input", pos=(20,20))
            self.textinput = wx.TextCtrl(self.panel, value="", pos=(80,20), size=(300,-1))
            self.gauge = wx.Gauge(self.panel,size=(300,20),pos=(80,80), style=wx.GA_HORIZONTAL)
            self.livelabel = wx.StaticText(self.panel, label="Time to live:", pos=(80,110))
            self.lltime = wx.StaticText(self.panel, label="30", pos=(160,110))
            self.saveButton =wx.Button(self.panel, label="Save Input", pos=(80,160))
            self.closeButton =wx.Button(self.panel, label="Cancel", pos=(180,160))
            self.timeoutButton =wx.Button(self.panel, label="Timer Off", pos=(280,160))
            self.saveButton.Bind(wx.EVT_BUTTON, self.SaveBusyString)
            self.closeButton.Bind(wx.EVT_BUTTON, self.OnQuit)
            self.timeoutButton.Bind(wx.EVT_BUTTON, self.OnNoTimeout)
            self.Bind(wx.EVT_CLOSE, self.OnQuit)
            self.timer = wx.Timer(self)
            self.Bind(wx.EVT_TIMER,self.OnTimer, self.timer)
            self.lifetimer = wx.Timer(self)
            self.Bind(wx.EVT_TIMER,self.OnLifeTimer, self.lifetimer)
            self.timer.Start(100)
            self.lifetimer.Start(1000)
            self.timeoutbutton_pressed = False
            self.gauge.SetBackgroundColour(wx.Colour(0, 127, 255, 255)) #Slate Blue
            self.gauge.SetRange(100)
            self.gauge.SetValue(0)
            self.life = 30
            self.direction = 1
            self.Show()
    
        def OnTimer(self, evt): #Update gauge
            x = int(self.gauge.GetValue())
            if x == 0:
                self.direction = 1
            elif x == 100:
                self.direction = -1
            x+=self.direction
            self.gauge.SetValue(x)
    
        def OnLifeTimer(self, evt): #Update time to live
            if self.timeoutbutton_pressed == True:
                return
            self.life -= 1
            self.lltime.SetLabelText(str(self.life))
            if self.life < 1:
                self.OnQuit(None)
    
        def OnNoTimeout(self, evt): # toggle time to live
            if self.timeoutbutton_pressed == False:
                self.timeoutbutton_pressed = True
                self.timeoutButton.SetLabel("Timer On")
            else:
                self.timeoutbutton_pressed = False
                self.timeoutButton.SetLabel("Timer Off")
    
        def OnQuit(self, event):
            self.timer.Stop()
            self.lifetimer.Stop()
            self.result_text = None
            self.Destroy()
    
        def SaveBusyString(self, event): # return input
            self.result_text = self.textinput.GetValue()
            self.timer.Stop()
            self.lifetimer.Stop()
            self.Destroy()
    
    app = wx.App()
    frame = MyFrame(None)
    frame.Show()
    app.MainLoop()
    

    Edit:
    You need a frame because the dialog to requires a parent, so the easiest way is to make a frame that you cannot see.
    Lose the MyFrame class in the above and change the app section of code to something like this:

    app = wx.App()
    frame = wx.Frame(None,-1,"",size=(1,1))
    frame.Show()
    dlg = Busy(parent = frame)
    dlg.ShowModal()
    print dlg.result_text # Do whatever here with the result I just print it
    dlg.Destroy()