Search code examples
pythonwxpython

Continuously check for radio button status [WxPython]


I have a listbox with a set of strings. The set of strings I want to display depends on which radio button is selected. I would like it such that while the user is interacting with the Form, if they ever change the radio button it will update the list box.

Here is my code (I'm leaving the array for t87 and t89 out because they are very long (assume they exist):

 def OnBtnSuperTesting(self, event):
    class MainWindow(wx.Frame):

        def __init__(self, parent, title):

            self.dirname=''

            wx.Frame.__init__(self, parent, title=title, size=(320,440))
            self.SetBackgroundColour(wx.WHITE)
            self.CenterOnScreen()
            self.CreateStatusBar()
            self.radioT89 = wx.RadioButton(self, -1, 'T89 only', pos = (2,0), style = wx.RB_GROUP)
            self.radioT87 = wx.RadioButton(self, -1, 'T87 only', pos = (154, 0))
            self.radioKeySort = wx.RadioButton(self, -1, 'Sort by Key', pos = (2,40), style = wx.RB_GROUP)
            self.radioAtoZ = wx.RadioButton(self, -1, 'Sort Name A-Z', pos = (2,60))
            self.radioZtoA = wx.RadioButton(self, -1, 'Sort Name Z-A', pos = (2,80))
            self.checkCode = wx.CheckBox(self, -1, 'Generate Code', pos = (154,40))
            self.checkBuild = wx.CheckBox(self, -1, 'Generate Build Report', pos = (154, 60))
            self.ln = wx.StaticLine(self, -1, pos = (0,15), size = (300,3), style = wx.LI_HORIZONTAL)
            self.ln2 = wx.StaticLine(self, -1, pos = (150,15), size = (3,100), style = wx.LI_VERTICAL)

            self.radioT87.Bind(wx.EVT_RADIOBUTTON, self.updateList)
            #self.Bind(wx.EVT_RADIOBUTTON, self.radioT89, self.updateList())




            self.listbox = wx.ListBox(self, -1, pos = (0,120), size = (300,200), choices = T89, style = (wx.LB_SINGLE|wx.LB_HSCROLL))
            self.go = wx.Button(self,-1, label = 'Go!', pos = (110, 325))



            # Setting up the menu.
            filemenu= wx.Menu()
            menuAbout= filemenu.Append(wx.ID_ABOUT, "&About"," Information about this program")
            menuExit = filemenu.Append(wx.ID_EXIT,"E&xit"," Terminate the program")

            # Creating the menubar.
            menuBar = wx.MenuBar()
            menuBar.Append(filemenu,"&File") 
            self.SetMenuBar(menuBar) 

            # Events.
            self.Bind(wx.EVT_MENU, self.OnExit, menuExit)
            self.Bind(wx.EVT_MENU, self.OnAbout, menuAbout)

            self.SetAutoLayout(1)

            self.Show()



        def OnExit(self,e):
            self.Close(True)  # Close the frame.

        def updateList(self):
            if  self.radioT87.GetValue() == True:
                choices = T87
                self.listbox.Set(choices)
            else:
                choices = T89
                self.listbox.Set(choices)
    app = wx.App(False)
    frame = MainWindow(None, "Supervisory Testing")
    app.MainLoop()

Solution

  • When you create each radiobutton you can create a bind event. What this does (as you have implemented later on in your code) is execute a command function when the bind event occurs. In your case it would look like this:

    self.Bind(wx.EVT_RADIOBUTTON,self.RadioButton,self.DoSomething)
    

    Explanation:

    wx.EVT_RADIOBUTTON
    

    This is the event that is triggered when the user changes the Radiobutton's status. It may or may not have attributes.

    self.RadioButton
    

    This is the radiobutton which you would like to bind. In your case "self.radioAtoZ" or similar.

    self.DoSomething
    

    THis is the callback function. You can make it whatever you want such as:

    def DoSomething(self):
        if self.radioAtoZ.getStatus():
            rearrangeNumbersFromAtoZ
            print 'Re-arranged numbers from A to Z'
        else:
            etc.
    

    EDIT:

    self.RadioButton.Bind(EVT_RADIOBUTTON, self.DoSomething)
    

    Your structure for self.DoSomething should be like this:

    Class MainWindow:
         def __init_(self, parent):
    
    
         def DoSomething(self):
             #dostuff
    

    Also in response to your other comment: when a function is called within a Bind event, it passes the event to the function by default. In addition, all functions have the "self" arg, thus 2 given args. You need to change the following:

    def DoSomething(self, event):
          #dostuff