Question

I am trying to use wx.Choice component to archieve a simple application.

The idea is, a number of items are listed in the wx.Choice, and each of them will trigger an unique function.

My first version of code was:

class MainFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, 0, 'wxPython pull-down choice', size = (400, 300))
        panel_select_model= wx.Panel(self, -1)
        model_list = ['Test_A', 'Test_B']
        self._model_type = None

        self._stat_tex = wx.StaticText(panel_select_model, 1, "Select Model Type:", (15, 20))
        self._droplist = wx.Choice(panel_select_model, 2, (150, 18), choices = model_list)

        """ Bind A Panel """
        self._droplist.SetSelection(0)
        self._droplist.Bind(wx.EVT_CHOICE, self.Test_A_click)

But it turns out that the two items in the dropdown list will trigger the same function (I expect that the Test_A will trigger that function and Test_B simply do nothing). So I try to bind Test_B to another method Test_B_click

class MainFrame(wx.Frame):

    def __init__(self):
        wx.Frame.__init__(self, None, 0, 'wxPython pull-down choice', size = (400, 300))
        panel_select_model= wx.Panel(self, -1)
        model_list = ['Test_A', 'Test_B']
        self._model_type = None

        self._stat_tex = wx.StaticText(panel_select_model, 1, "Select Model Type:", (15, 20))
        self._droplist = wx.Choice(panel_select_model, 2, (150, 18), choices = model_list)

        """ Bind A Panel """
        self._droplist.SetSelection(0)
        self._droplist.Bind(wx.EVT_CHOICE, self.Test_A_click)

        """ Bind B Panel """
        self._droplist.SetSelection(1)
        self._droplist.Bind(wx.EVT_CHOICE, self.Test_B_click)

The above code display a main frame, a drop list in it and two items in the drop list. However, when I click either of the two items, no function is triggered anymore.

So, how can I archieve my goal: Bind different functions to each of the items in a wx.Choice component, and make them trigger functions correctly.

Thanks.

Was it helpful?

Solution 2

I am coming back to ask my own question. I don't think this is the perfect solution, but it managed my way out.

Here is the code:

class MainFrame(wx.Frame):

def __init__(self):
    wx.Frame.__init__(self, None, 0, 'wxPython pull-down choice', size = (400, 300))
    panel_select_model= wx.Panel(self, -1)
    model_list = ['Test_A', 'Test_B']
    self._model_type = None

    self._stat_tex = wx.StaticText(panel_select_model, 1, "Select Model Type:", (15, 20))
    self._droplist = wx.Choice(panel_select_model, 2, (150, 18), choices = model_list)

    """ Bind A Panel """
    self._droplist.SetSelection(0)
    self._droplist.Bind(wx.EVT_CHOICE, self.choice_click)

    """ Bind B Panel """
    self._droplist.SetSelection(1)
    self._droplist.Bind(wx.EVT_CHOICE, self.choice_click)

def choice_click(self, event):
    if self._droplist.GetStringSelection() == "Test_A":
        self.Test_A__click()
    elif self._droplist.GetStringSelection() == "Test_B":
        self.Test_B_click()

In above code. I put another layer between the wx.Choice component and the functions that I would like to trigger. Once we have a match, its corresponding function will be triggered.

I am afraid this is not an effective way. So I would be extremely appreciate if anyone can bring up a good solution. Thanks a lot.

OTHER TIPS

Your methodology is probably the most common way to do what you want and it's pretty easy to tell what's going on as well. However if you do this with a little dash of meta-programming that might be a little cleaner if you set it up correctly:

import wx

########################################################################
class MyFrame(wx.Frame):

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, None, title="Callbacks")
        panel = wx.Panel(self)
        self.choice = wx.Choice(panel, choices=["test_A", "test_B"])
        self.choice.Bind(wx.EVT_CHOICE, self.onChoice)
        self.Show()

    #----------------------------------------------------------------------
    def onChoice(self, event):
        choice = self.choice.GetStringSelection()
        method = getattr(self, "on_%s" % choice)
        method()

    #----------------------------------------------------------------------
    def on_test_A(self):
        print "You chose test_A!"

    #----------------------------------------------------------------------
    def on_test_B(self):
        print "You chose test_B!"


#----------------------------------------------------------------------
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyFrame()
    app.MainLoop()

Here we use Python's getattr function to determine which method to actually call. This allows us to skip the use of the if statement, but assumes that we have all the methods set up for all the choices in the control.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top