Рубрики
Без рубрики

WxPython: добавление и удаление виджетов динамически

Получите практические, реальные навыки Python на наших ресурсах и пути

Автор оригинала: Mike Driscoll.

Я продолжаю видеть людей, спрашивающих о том, как добавлять или удалять виджеты после того, как они уже начали свое приложение WXPYPHON. Это на самом деле то, что действительно легко сделать, поэтому я решил, что пришло время написать простое руководство по теме. Я должен был сделать это время от времени, в зависимости от того, какой пользователь доступа к моей программе, чтобы я мог показать немного разные варианты. Во всяком случае, давайте начнем!

Я решил сделать это действительно просто. Все это приложение будет делать, это позволяет пользователю добавлять или удалять кнопки. Следующий скрипт создаст окно, аналогичное одному в начале этой статьи. Если вы нажмете кнопку «Добавить» несколько раз, вы должны увидеть что-то вроде этого:

Как видите, вы в конечном итоге с большей кнопками! Теперь давайте найму минутку и прочитайте код. Я объясню это, как только вы закончите, читая это.

import wx

########################################################################
class MyPanel(wx.Panel):
    """"""

    #----------------------------------------------------------------------
    def __init__(self, parent):
        """Constructor"""
        wx.Panel.__init__(self, parent)
        self.number_of_buttons = 0
        self.frame = parent
        
        self.mainSizer = wx.BoxSizer(wx.VERTICAL)
        controlSizer = wx.BoxSizer(wx.HORIZONTAL)
        self.widgetSizer = wx.BoxSizer(wx.VERTICAL)
        
        self.addButton = wx.Button(self, label="Add")
        self.addButton.Bind(wx.EVT_BUTTON, self.onAddWidget)
        controlSizer.Add(self.addButton, 0, wx.CENTER|wx.ALL, 5)
        
        self.removeButton = wx.Button(self, label="Remove")
        self.removeButton.Bind(wx.EVT_BUTTON, self.onRemoveWidget)
        controlSizer.Add(self.removeButton, 0, wx.CENTER|wx.ALL, 5)
        
        self.mainSizer.Add(controlSizer, 0, wx.CENTER)
        self.mainSizer.Add(self.widgetSizer, 0, wx.CENTER|wx.ALL, 10)
        
        self.SetSizer(self.mainSizer)
        
    #----------------------------------------------------------------------
    def onAddWidget(self, event):
        """"""
        self.number_of_buttons += 1
        label = "Button %s" %  self.number_of_buttons
        name = "button%s" % self.number_of_buttons
        new_button = wx.Button(self, label=label, name=name)
        self.widgetSizer.Add(new_button, 0, wx.ALL, 5)
        self.frame.fSizer.Layout()
        self.frame.Fit()
    
    #----------------------------------------------------------------------
    def onRemoveWidget(self, event):
        if self.widgetSizer.GetChildren():
            sizer_item = self.widgetSizer.GetItem(self.number_of_buttons-1)
            widget = sizer_item.GetWindow()
            self.widgetSizer.Hide(widget)
            widget.Destroy()
            self.number_of_buttons -= 1
            self.frame.fSizer.Layout()
            self.frame.Fit()
                
########################################################################
class MyFrame(wx.Frame):
    """"""

    #----------------------------------------------------------------------
    def __init__(self):
        """Constructor"""
        wx.Frame.__init__(self, parent=None, title="Add / Remove Buttons")
        self.fSizer = wx.BoxSizer(wx.VERTICAL)
        panel = MyPanel(self)
        self.fSizer.Add(panel, 1, wx.EXPAND)
        self.SetSizer(self.fSizer)
        self.Fit()
        self.Show()
        
#----------------------------------------------------------------------
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyFrame()
    app.MainLoop()
    

Я думаю, что это довольно прямой код, поэтому мы просто будем сосредоточиться на важных битах. Первая тема, которую я собираюсь указать, состоит в том, что я называю методом FARM () прямо, прежде чем показать это. Обычно я избегаю использования в форме, но у меня возникли проблемы с получением кадра, чтобы соответствовать размеру, всякий раз, когда я добавил или удалил кнопки и фиксировал эту проблему для меня. Я должен отметить, что в FIT всегда пытается сделать виджеты в соответствии с контейнером, а иногда он в конечном итоге делает его таким образом, как мне не нравится.

В любом случае, другой бит в методах OnAddwidget и Onremovewidget. Вы обычно хотите позвонить на размещении на объекте контейнера, чтобы сделать его обновление и расположение элементов управления всякий раз, когда вы добавляете или удалите виджет. Как ни странно, кажется, что подходит это автоматически, поэтому те макет () звонит, которые вы видите в коде выше, действительно можно удалить. Я попытался удалить подходящие, чтобы увидеть, было ли достаточно ли макета, но когда вы это делаете, рамка не обновляет свой размер, поэтому пригодность, кажется, требуется в этом случае. Теперь, если вы получили добавление или удаление виджетов таким образом, чтобы он не повлиял на общий размер кадра, я думаю, что планировка будет достаточно.

Наконец, в качестве побочной записи вы иногда используете макет () в конце обновления замораживания/оттепенности.

Хорошо, вот и все! Теперь вы также должны быть в состоянии добавлять или удалять виджеты после того, как ваше приложение запущено. Я надеюсь, что вы узнали что-то новое.