wxpython - 使用循环创建独特的 GUI 元素

发布于 2024-11-08 03:49:31 字数 2882 浏览 3 评论 0原文

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

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

实际上放置这些应该很容易,但更重要的是,我需要它们在某种程度上都是唯一的,这样我就可以单独更改每个标签或单独获取每个单选框的每个值。

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

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)

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

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..

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

污味仙女 2024-11-15 03:49:31

自从我完成任何 wxPython 编码以来已经有一段时间了,所以我有点生疏了,但是除了 neurino 的解决方案之外,我还能想到两种方法来做到这一点,尽管还有其他变体。


方法 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 事件绑定到同一个处理程序即可。然后在处理程序中,您可以使用标签属性来区分 RadioBox。

工作示例:

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,那么我可能只是将该对制作为一个丰富的复合小部件,并提供一些更改标签等的方法。然后使用方法2来创建和更新它们。如果您需要在创建后在事件处理程序之外修改这些小部件属性,那么我认为您需要以某种形式或形式保留对它们的引用,例如方法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()

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()
沉溺在你眼里的海 2024-11-15 03:49:31

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

如果您负责创建(或检索)id,并将它们存储(在列表中,在字典中,您选择),那么您将能够返回所有单个元素来编辑它。

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

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文