wxpython - Создание уникальных элементов графического интерфейса с помощью цикла

1

Я пытаюсь создать графический интерфейс с большим количеством элементов, где есть несколько наборов одной и той же вещи (шесть ярлыков и шесть радиобокс).

Что я хочу сделать (чтобы сэкономить место и опыт обучения) - создать какой-то цикл для размещения этих элементов на панели, которую я использую.

На самом деле их размещение должно быть легким, но кикер, мне нужно, чтобы все они были уникальны, поэтому я могу индивидуально изменить каждую метку или получить каждое значение каждого радиоблока в отдельности.

Ниже приведен код, который я имею прямо сейчас, где все элементы индивидуально созданы и размещены.

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)

Кроме того, поздно. Итак, если я не понимаю смысла, дайте мне знать, и я буду рад снова объяснить.

  • 0
    Почему вы соединяете пустой StaticText с каждым RadioBox? Вы знаете, что Radiobox предоставляет название?
  • 0
    Статический текст должен соответствовать радиобоксу не как заголовок, а как то, что я выберу позже через код с выбором переключателей.
Теги:
wxpython

2 ответа

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

Если по какой-то причине вам нужен пустой StaticText, который вы связали с каждым RadioBox, тогда я бы просто сделал эту пару богатым компостированным виджетами с некоторыми методами изменения метки и т.д. Затем используйте метод 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()
  • 0
    Мне они нужны. Оглядываясь назад, я должен был опубликовать все .. Но я использую структуру MVC, поэтому пустые staticTexts обновляются при запуске программы.
  • 0
    Какой текст будет добавлен к ним при запуске программы? это изменится позже? может ли оно иметь разные значения при запуске программы?
Показать ещё 1 комментарий
0

Они будут уникальными в любом случае, если вы не предоставите id, который вы можете создать с помощью wx.NewId() wx создаст его для вас.

Если вы позаботились о создании (или извлечении) идентификаторов и сохранили их (в списке, в dict, вы выбираете), то вы сможете вернуться ко всему отдельному элементу, чтобы его отредактировать.

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

В любом случае вы должны иметь возможность делать свои изменения, которые обычно отвечают на действия пользователя, только используя данные событий без необходимости хранить какой-либо идентификатор.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню