
Создание и удаление виджетов являются довольно распространёнными заданиями, но большинство разработчиков не в восторге от него. Однако, wxPython способен значительно упростить данный процесс. Я сам неоднократно разрабатывал виджеты, основываясь на том, какие функции необходимы конечному пользователю программы, так что я могу ознакомить вас с массой вариантов. Например, администратор может получить дополнительные возможности, доступа к которым простые пользователи иметь не будут. В этом случае возникает ситуация, когда вам нужно быстро убрать или добавить административную панель с виджетами.
Я, к примеру, решил эту проблему очень просто. Это приложение даёт пользователям возможность добавлять и убирать кнопки, и ничего больше. Скрипт, который вы найдёте ниже, позволит вам создать окно, похожее на то, что вы видите в начале статьи. Когда вы нажмёте кнопку «Add» несколько раз, вы должны будете увидеть что-то вроде этого:

Как вы могли заметить, вы добавили несколько кнопок. Теперь давайте уделим мгновение и прочтём код. Я объясню этот код сразу же после того, как вы его прочтёте.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | 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():             self.widgetSizer.Hide(self.number_of_buttons-1)             self.widgetSizer.Remove(self.number_of_buttons-1)             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() | 
Я думаю, что это довольно простой код, так что я сфокусирую ваше внимание на важных битах. Первая тема, о которой я хотел бы рассказать, это метод под названием Frame’s Fit(). Я обычно избегаю использования фита, но у меня были проблемы с изменением размера окна в момент добавления новых кнопок, и фит справился с этим. Стоит отметить, что фит постоянно пытается подогнать виджеты под окно, и, иногда, мне не нравится как это выглядит.
Как бы то ни было, следующий бит демонстрирует методы onAddWidget и onRemoveWidget. Обычно вам требуется два слоя: первый отвечает за размеры и обновления контейнера, второй за добавление и удаление виджетов. Весьма странно, но похоже, что фит делает это автоматически, так что вы можете смело удалять всё, что находится выше строки Layout(). Я убирал фиты, чтобы проверить, справится ли Layout с задачей подгона под контейнер, но как только я удалил фиты, размер контейнера перестал подстраиваться под количество кнопок, так что без фитов в данном случае не обойтись. Однако, если вы добавляете виджеты, которые точно поместятся в контейнере, вам будет достаточно и одного Layout.
В конце я хотел бы добавить небольшой комментарий. Вы также можете использовать Layout() в конце обновления Freeze / Thaw.
Подведем итоги
Благодаря этой статье вы должны научиться добавлять и удалять виджеты довольно быстро. Когда вы полностью освоите данное приложение, вы будете поражены его простотой и эффективностью. Это фрагмент информации, который я считаю очень полезным, так как сам пользуюсь данной техникой на протяжении многих лет.
Продолжение
Следующий урок №2: Как сделать скриншот вашего приложения

Являюсь администратором нескольких порталов по обучению языков программирования Python, Golang и Kotlin. В составе небольшой команды единомышленников, мы занимаемся популяризацией языков программирования на русскоязычную аудиторию. Большая часть статей была адаптирована нами на русский язык и распространяется бесплатно.
E-mail: vasile.buldumac@ati.utm.md
Образование
Universitatea Tehnică a Moldovei (utm.md)
- 2014 — 2018 Технический Университет Молдовы, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
- 2018 — 2020 Технический Университет Молдовы, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»