Search code examples
python-2.7wxpythonwxwidgets

wxpython-how to get return value from custom wx dialog


This is follow up question from wxpython-can we add ok button on pybusyinfo dialog?

I have created custom dialog.It will pop up when we call a function from another function and if user clicks "Dont proceed" button on the dialog window i need to get true/False value to intimate whether particular button is pressed or not and pass that value to function call to proceed further.

But with wx custom dialog i could not any return value since the dialog getting destroyed once we press any button.

Is there any way to get return value from custom dialog class with button click event and can access from outside of class even if it is destroyed.

Thanks in advance.

def main():
    print "start execution"
    ret = getUserInput("Do you want to proceed?")
    if ret:
        print "proceed"
    else:
        print "exit"
def getUserInput(msg):
    class Busy(wx.Dialog):
        def __init__(self, parent, msg):
            wx.Dialog.__init__(self, parent, wx.ID_ANY, "Message", size=(420, 200))
            self.panel = wx.Panel(self, wx.ID_ANY)

            self.label = wx.StaticText(self.panel, label=msg, pos=(20, 20))

            self.gauge = wx.Gauge(self.panel, size=(300, 20), pos=(50, 50), style=wx.GA_HORIZONTAL)
            self.livelabel = wx.StaticText(self.panel, label="Time to live:", pos=(50, 80))
            self.lltime = wx.StaticText(self.panel, label="30", pos=(130, 80))
            self.notProceedButton = wx.Button(self.panel, label="Don't proceed", pos=(50, 100))

            self.timeoutButton = wx.Button(self.panel, label="Timer Off", pos=(250, 100))
            self.notProceedButton.Bind(wx.EVT_BUTTON, self.notProceed)

            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.result_text = True


        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.Destroy()


        def notProceed(self, event):  # return input
            self.result_text = False
            self.timer.Stop()
            self.lifetimer.Stop()
            self.Destroy()

    app = wx.App()

    dlg = Busy(parent = None, msg=msg)
    dlg.ShowModal()

    return dlg.result_text 

Solution

  • Sure. The EndModal method will return whatever return code you want. Ie

        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.EndModal(SOME_ID_THAT_YOU_DEFINED_SOMEWHERE_ELSE)
                self.OnQuit(None)
    

    The argument passed to EndModal is returned from ShowModal

    app = wx.App()
    
    dlg = Busy(parent = None, msg=msg)
    return_code = dlg.ShowModal()
    

    As a side note, you don't have to call Destroy from within the dialog. If you want to retrieve some flag or other information from it you can call Destroy after, ie

    app = wx.App()
    
    dlg = Busy(parent = None, msg=msg)
    return_value = dlg.ShowModal()
    some_other_value = dlg.some_other_value
    dlg.Destroy()