wxpython - 使用循环创建唯一的GUI元素

时间:2011-05-20 07:23:56

标签: python wxpython

我正在尝试创建一个包含大量项目的GUI,其中有几组相同的东西(六个标签和六个radioboxes)。

我想要做的是(为了节省空间和学习经验)是创建某种循环来将这些元素放在我正在使用的面板上。

实际放置这些应该很容易,但是踢球者,我需要它们在某些方面都是独一无二的,所以我可以单独更改每个标签或单独获取每个无线电放大器的每个值。

下面是我现在的代码,其中所有元素都是单独创建和放置的。

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)

此外,已经很晚了。所以,如果我没有意义,请告诉我,我将很乐意重新解释..

2 个答案:

答案 0 :(得分:2)

我已经有一段时间了,因为我已经完成了任何wxPython编码,所以我有点生疏,但除了神经纤维的解决方案外,我可以想到两种方法,尽管还有其他的变化。


方法1

使用窗口小部件标签作为键,保持对字典中每个窗口小部件的引用,例如

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

方法2

就个人而言,我更喜欢采用更多事件驱动的方法。只需将每个RadioBoxes事件绑定到同一个处理程序即可。然后在处理程序中,您可以使用其标签属性区分RadioBoxes

工作示例:

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

如果由于某种原因你需要与每个RadioBox配对的那个空的StaticText,那么我可能只是将该对组成一个丰富的compostite小部件,使用一些方法来更改标签等。然后使用方法2 < / em>创建和更新它们。如果您需要在创建事件处理程序之外修改这些窗口小部件属性,那么我认为您需要以某种形式或形式保留对它们的引用,例如方法1

这是一个工作示例

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

答案 1 :(得分:0)

无论如何,它们都是独一无二的,如果您没有提供id,您可以使用wx.NewId()创建,wx将为您创建一个。

如果你负责创建(或检索)id并存储它们(在列表中,在dict中,你选择),那么你将能够回到所有单个元素进行编辑。

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

无论如何,您应该能够进行编辑,通常只响应用户操作,只使用事件数据,而无需存储任何ID。