Nithya
Nithya

Reputation: 644

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 

Upvotes: 3

Views: 3843

Answers (2)

Rolf of Saxony
Rolf of Saxony

Reputation: 22443

Courtesy of user2682863's excellent example of EndModal()

import wx
class getUserInput(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.EndModal(True)

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

app = wx.App()
dlg = getUserInput(parent = None, msg="Do you want to porceed?")
ret = dlg.ShowModal()
if ret:
    print "proceed"
else:
    print "exit"

Upvotes: 1

user2682863
user2682863

Reputation: 3217

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

Upvotes: 4

Related Questions