views:

736

answers:

3

In wxPython, if I create a list of radio buttons and place the list initially, is it possible to change the contents in that list later?

For example, I have a panel that uses a boxSizer to place the widgets initially. One of those widgets is a list of radio buttons (I have also tried a normal radiobox). I would like to dynamically change the list based on variables from another class.

However, once the list is placed in the sizer, it's effectively "locked"; I can't just modify the list and have the changes appear. If I try re-adding the list to the sizer, it just gets put in the top left corner of the panel.

I'm sure I could hide the original list and manually place the new list in the same position but that feels like a kludge. I'm sure I'm making this harder than it is. I'm probably using the wrong widgets for this, much less the wrong approach, but I'm building this as a learning experience.

    class Job(wiz.WizardPageSimple):
    """Character's job class."""

    def __init__(self, parent, title, attribs):
        wiz.WizardPageSimple.__init__(self, parent)
        self.next = self.prev = None
        self.sizer = makePageTitle(self, title)
        self.charAttribs = attribs

#---Create widgets
        self.Job_list = ["Aircraft Mechanic", "Vehicle Mechanic", "Electronics Specialist"]

        box1_title = wx.StaticBox( self, -1, "" )
        box1 = wx.StaticBoxSizer( box1_title, wx.VERTICAL )
        grid1 = wx.BoxSizer(wx.VERTICAL)
        for item in self.Job_list:
            radio = wx.RadioButton(self, -1, item)
            grid1.Add(radio)

##Debugging
        self.btn = wx.Button(self, -1, "click")
        self.Bind(wx.EVT_BUTTON, self.eligibleJob, self.btn)

#---Place widgets
        self.sizer.Add(self.Job_intro)
        self.sizer.Add(self.btn)
        box1.Add(grid1)
        self.sizer.Add(box1)        

    def eligibleJob(self, event):
        """Determine which Jobs a character is eligible for."""

        if self.charAttribs.intelligence >= 12:
            skillList = ["Analyst", "Interrogator", "Fire Specialist", "Aircraft Pilot"]
            for skill in skillList:
                self.Job_list.append(skill)
            print self.Job_list ##Debugging
        #return self.Job_list
A: 

Two possible solutions

  1. Rebuild the sizer with the radio widgets each time you have to make a change
  2. Hold the radio button widgets in a list, and call SetLabel each time you have to change their labels.
Eli Bendersky
+1  A: 

To make new list elements appear in correct places, you have to re-layout the grid after adding new elements to it. For example, to add a few new items, you could call:

def addNewSkills(self, newSkillList):
    '''newSkillList is a list of skill names you want to add'''
    for skillName in newSkillList:
        newRadioButton = wx.RadioButton(self, -1, skillName)
        self.grid1.Add(newRadioButton) # appears in top-left corner of the panel
    self.Layout() # all newly added radio buttons appear where they should be
    self.Fit() # if you need to resize the panel to fit new items, this will help

where self.grid1 is the sizer you keep all your radio buttons on.

DzinX
A: 

I was able to fix it by using the info DzinX provided, with some modification.

It appears that posting the radio buttons box first "locked in" the box to the sizer. If I tried to add a new box, I would get an error message stating that I was trying to add the widget to the same sizer twice.

By simply removing the radio buttons initially and having the user click a button to call a method, I could simply add a the list of radio buttons without a problem.

Additionally, by having the user click a button, I did not run into errors of "class Foo has no attribute 'bar'". Apparently, when the wizard initalizes, the attributes aren't available to the rest of the wizard pages. I had thought the wizard pages were dynamically created with each click of "Next" but they are all created at the same time.

crystalattice