1

I am attempting to create a GUI with a large amount of items where there are several sets of the same thing (six labels and six radioboxes).

What I want to do (to save space and for a learning experience) is to create some sort of loop to place these elements on the panel I am using.

Actually placing these should be easy, but the kicker is, I need them to all be unique in some way so I can individually change each label or get each value of each radiobox individually.

Below is the code I have right now, where all the elements are individually created and placed.

sizerMain = wx.BoxSizer()
## For the main control area
panelControl = wx.Panel(self,1,style = wx.MAXIMIZE)
sizerControl = wx.GridBagSizer(hgap = 4,vgap = 4)

# Add widgets
## Main content area
lblTitle = wx.StaticText(panelControl,label = "Pick Scores")
sizerControl.Add(lblTitle,pos = (0,0),
                 flag = wx.ALIGN_CENTER|wx.TOP|wx.LEFT|wx.BOTTOM,
                 border = 5)

self.btnRoll = wx.Button(panelControl,label = "Roll!")
sizerControl.Add(self.btnRoll,pos = (0,1),span = (1,5),
                 flag = wx.EXPAND|wx.LEFT|wx.RIGHT,border = 5)
### Radio boxes
#### Radio button tuple
rboxPick = ["Default","Strength","Dexterity","Constitution",
            "Intelligence","Wisdom","Charisma"]

self.lblRoll1 = wx.StaticText(panelControl)
sizerControl.Add(self.lblRoll1,pos = (1,0),flag = wx.ALIGN_CENTER)
self.rboxRoll1 = wx.RadioBox(panelControl,label = "Roll One",choices = rboxPick)
sizerControl.Add(self.rboxRoll1,pos = (1,1),span = (1,5),
                 flag = wx.EXPAND|wx.LEFT|wx.RIGHT,border = 2)

self.lblRoll2 = wx.StaticText(panelControl)
sizerControl.Add(self.lblRoll2,pos = (2,0),flag = wx.ALIGN_CENTER)
self.rboxRoll2 = wx.RadioBox(panelControl,label = "Roll Two",choices = rboxPick)
sizerControl.Add(self.rboxRoll2,pos = (2,1),span = (1,5),
                 flag = wx.EXPAND|wx.LEFT|wx.RIGHT,border = 2)

self.lblRoll3 = wx.StaticText(panelControl)
sizerControl.Add(self.lblRoll3,pos = (3,0),flag = wx.ALIGN_CENTER)
self.rboxRoll3 = wx.RadioBox(panelControl,label = "Roll Three",choices = rboxPick)
sizerControl.Add(self.rboxRoll3,pos = (3,1),span = (1,5),
                 flag = wx.EXPAND|wx.LEFT|wx.RIGHT,border = 2)

self.lblRoll4 = wx.StaticText(panelControl)
sizerControl.Add(self.lblRoll4,pos = (4,0),flag = wx.ALIGN_CENTER)
self.rboxRoll4 = wx.RadioBox(panelControl,label = "Roll Four",choices = rboxPick)
sizerControl.Add(self.rboxRoll4,pos = (4,1),span = (1,5),
                 flag = wx.EXPAND|wx.LEFT|wx.RIGHT,border = 2)

self.lblRoll5 = wx.StaticText(panelControl)
sizerControl.Add(self.lblRoll5,pos = (5,0),flag = wx.ALIGN_CENTER)
self.rboxRoll5 = wx.RadioBox(panelControl,label = "Roll Five",choices = rboxPick)
sizerControl.Add(self.rboxRoll5,pos = (5,1),span = (1,5),
                 flag = wx.EXPAND|wx.LEFT|wx.RIGHT,border = 2)

self.lblRoll6 = wx.StaticText(panelControl)
sizerControl.Add(self.lblRoll6,pos = (6,0),flag = wx.ALIGN_CENTER)
self.rboxRoll6 = wx.RadioBox(panelControl,label = "Roll Six",choices = rboxPick)
sizerControl.Add(self.rboxRoll6,pos = (6,1),span = (1,5),
                 flag = wx.EXPAND|wx.LEFT|wx.RIGHT,border = 2)

Also, it is late.. So if I am not making sense please let me know and I will be happy to re-explain..

2
  • Why are you pairing an empty StaticText with each RadioBox ? are you aware that Radiobox provides a title? Commented May 20, 2011 at 8:35
  • The static text is to matched to the radiobox, not as a title but as something I select later through code with the selection of the radio buttons. Commented May 20, 2011 at 16:11

2 Answers 2

2

Its been a while since I've done any wxPython coding so I'm a little rusty, but off the top of my head I can think of two ways of doing this other than neurino's solution, although there are other variations.


Method 1

Keep references to each widget in a dictionary, using the widgets label as the key, eg

rboxPick = ["Default", "Strength", "Dexterity", "Constitution", "Intelligence", "Wisdom", "Charisma"]
labels = ["One", "Two", "Three", "Four"]            
self.rollRbs = dict()

#create  the radioBoxes..
for row, label in enumerate(labels):
    lbl = wx.StaticText(panelControl)       
    rbox = wx.RadioBox(panelControl, label="Roll %s"%(label), 
                       choices=rboxPick)              
    sizerControl.Add(rbox ,pos = (row, 1),span=(1,5),
                     flag=wx.EXPAND|wx.LEFT|wx.RIGHT,border = 2)

    self.rollRbs[rbox.GetLabel()] = rbox

#changing the label...
self.rollRbs["Roll One"].SetLabel("blah")

Method 2

Personally I prefer a more event driven approach. Simply bind each RadioBoxes event to the same handler. Then in the handler you can differentiate between the RadioBoxes using their label attributes.

Working example:

import wx

class GUI(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(700, 400))

        panelControl = wx.Panel(self, 1, style=wx.MAXIMIZE) 
        sizerControl = wx.GridBagSizer(hgap=4,vgap = 4)

        lblTitle = wx.StaticText(panelControl, label="Pick Scores")             
        self.btnRoll = wx.Button(panelControl, label="Roll!")

        sizerControl.Add(lblTitle, pos=(0,0), 
                         flag=wx.ALIGN_CENTER|wx.TOP|wx.LEFT|wx.BOTTOM, border=5) 
        sizerControl.Add(self.btnRoll, pos=(0,1), 
                         span=(1,5), flag=wx.EXPAND|wx.LEFT|wx.RIGHT, border=5)

        rboxPick = ["Default", "Strength", "Dexterity", "Constitution", 
                    "Intelligence", "Wisdom", "Charisma"
                    ]
        labels = ["One", "Two", "Three", "Four"]

        #Create, layout and bind the RadioBoxes
        for row, label in enumerate(labels):
            lbl = wx.StaticText(panelControl)       
            rbox = wx.RadioBox(panelControl, label="Roll %s"%(label), choices=rboxPick)
            self.Bind(wx.EVT_RADIOBOX, self.onRadioBox, rbox)              
            sizerControl.Add(rbox, pos=(row+1, 1), span=(1,5), 
                             flag=wx.EXPAND|wx.LEFT|wx.RIGHT,border=2)

        sizerMain = wx.BoxSizer()
        sizerMain.Add(sizerControl)
        panelControl.SetSizerAndFit(sizerMain)

    def onRadioBox(self, evt):
        """Event handler for RadioBox.."""

        rbox = evt.GetEventObject()#Get a reference to the RadioBox
        rboxLbl = rbox.GetLabel()   #We can identify the RadioBox with its label
        selection = rbox.GetSelection()

        print rboxLbl
        print selection

        if rboxLbl == "Roll One":
            #do something
            pass     
        elif rboxLbl == "Roll Two":
             #do something else
            pass


if __name__ == "__main__":
    app = wx.PySimpleApp()
    frame = GUI(None, -1, "") 
    frame.Show(1)
    app.MainLoop()

If for some reason you need that empty StaticText that you have paired with each RadioBox, then I would probably just make that pair a rich compostite widget, with some methods for changing the label etc. Then use method 2 to create and update them. If you need to modify these widgets attributes outside of the event handler after they are created then I think your going need to keep references to them in some shape or form e.g method 1.

Here is a working example

import wx
import  wx.lib.newevent

class LblRadBox(wx.Panel):
    """
    Simple example of a composite widget 
    Add methods as required to improve functionality...
    """
    def __init__(self, parent, stLbl="", rbLbl="", choices=[]):
        wx.Panel.__init__(self, parent)
        self.stLbl = wx.StaticText(self, label=stLbl)       
        self.rbox = wx.RadioBox(self, label=rbLbl, choices=choices)

        sizer =  wx.BoxSizer()
        sizer.Add(self.stLbl)
        sizer.Add(self.rbox)
        self.SetSizerAndFit(sizer)

    def SetSTLabel(self, lbl):
        self.stLbl.SetLabel(lbl)

    def GetLabel(self):
        return self.rbox.GetLabel()

    def GetSelection(self, lbl):
        return self.rbox.GetSelection()

class GUI(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(700, 400))

        panelControl = wx.Panel(self, 1, style=wx.MAXIMIZE) 
        sizerControl = wx.GridBagSizer(hgap=4,vgap = 4)

        lblTitle = wx.StaticText(panelControl, label="Pick Scores")             
        self.btnRoll = wx.Button(panelControl, label="Roll!")

        sizerControl.Add(lblTitle, pos=(0,0), 
                         flag=wx.ALIGN_CENTER|wx.TOP|wx.LEFT|wx.BOTTOM, border=5) 
        sizerControl.Add(self.btnRoll, pos=(0,1), 
                         span=(1,5), flag=wx.EXPAND|wx.LEFT|wx.RIGHT, border=5)

        rboxPick = ["Default", "Strength", "Dexterity", "Constitution", 
                    "Intelligence", "Wisdom", "Charisma"
                    ]
        labels = ["One", "Two", "Three", "Four"]

        #Create, layout and bind the RadioBoxes
        for row, label in enumerate(labels):        
            rbox = LblRadBox(panelControl, rbLbl="Roll %s"%(label), choices=rboxPick) 
            #if u want to be able to access the rboxes outside of onRadioBox() 
            #then add references of them to a dictionary like in method 1..

            sizerControl.Add(rbox, pos=(row+1, 1), span=(1,5), 
                             flag=wx.EXPAND|wx.LEFT|wx.RIGHT,border=2)

        panelControl.Bind(wx.EVT_RADIOBOX, self.onRadioBox)    

        sizerMain = wx.BoxSizer()
        sizerMain.Add(sizerControl)
        panelControl.SetSizerAndFit(sizerMain)

    def onRadioBox(self, evt):
        """Event handler for RadioBox.."""
        rbox = evt.GetEventObject()#Get a reference to the RadioBox
        rboxLbl = rbox.GetLabel()   #We can identify the RadioBox with its label
        selection = rbox.GetSelection()

        print rboxLbl
        print selection

        if rboxLbl == "Roll One":
            #do something
            pass     
        elif rboxLbl == "Roll Two":
             #do something else
            pass


if __name__ == "__main__":
    app = wx.PySimpleApp()
    frame = GUI(None, -1, "") 
    frame.Show(1)
    app.MainLoop()
Sign up to request clarification or add additional context in comments.

3 Comments

I do need them. in retrospect I should have posted everything.. But I am using MVC structure, so the empty staticTexts are updated on program start.
What text will be added to them at the program start? does it change later? can it have different values at program start?
Ok I just read your other comment on your question... so would I be right in saying that the StaticText will change based on the selection in the RadioBox? at any rate, it seems like the best to do this is as per my last suggestion in my answer, implement the pair as a composite widget on a panel.
0

They will be unique anyway, if you do not provide an id you can create with wx.NewId() wx will create one for you.

If you take care of creating (or retrieving) ids, and store them (in a list, in a dict, you choose), then you'll be able to get back to all single element to edit it.

ids = []
for lbl in ('Name', 'Surname', 'Address'):
    st = wx.StaticText(panel)
    tc = wx.TextControl(panel, label=lbl)
    ids.append(tc.GetId())

Anyway you should be able to make your edits, that usually respond to user actions, only using events data without the need of storing any id.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.