Если вы новичок в использовании wxPython, но уже знакомы с XML, вам может пригодиться данная статья. Почему? Потому, что wxPython поддерживает XRC, один из форматов файла XML, описывающий графический интерфейс в XML. На самом деле, документация и демо-пакеты wxPython содержат лишь редактор для создания и проведения различных манипуляций с этим форматом. Он называется XRCed. В этой статье я проведу вам небольшую экскурсию по XRCed, расскажу о его возможностях и его основном предназначении.
Есть вопросы по Python?
На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!
Паблик VK
Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!
Весьма странно, что XRCed, который когда-то ещё не был частью wxPython, до сих пор имеет собственный веб-сайт. Мне сказали, что предыдущая версия отлично работает со считывателями (программами, озвучивающими интерфейс для слепых и слабовидящих), особенно в сравнении с последней версией, привязанной к демо-пакету. Так что, если вы у вас проблемы со зрением, то вам будет намного удобнее использовать предыдущую версию. Конечно, прошлая версия не обновлялась с 2007… Однако, каждому своё.
Приступая к работе
Как только вы установите демо-приложение, запустите инструмент, который называется XRC Resource Editor. Его главный экран выглядит как на скриншоте выше. Вы также увидите второе окно поменьше, которое выглядит вот так:
Второе окно позволяет вам добавлять в интерфейс различные виджеты. Для того, чтобы на самом деле понять, как это работает, нам нужно будет создать простое приложение.
Создаём наше первое приложение
Давайте создадим простое двухкнопочное приложение с помощью XRCed. Оно будет абсолютно бесполезно, но отлично подойдёт в качестве примера графического интерфейса, который создавался впопыхах.
Вы должны увидеть безымянную wxFrame, появляющуюся в правой части приложения, отображающуюся как рут в древе виджетов (это хорошо видно на скриншотах в начале статьи). Для этого примера мы собираемся назвать этот фрейм “MainFrame”. Теперь, выбрав этот фрейм в древе, добавьте панель, которая будет называться “MainPanel”.
Затем, на втором всплывающем окне (мы его описывали выше), есть ряд кнопок, расположенный вверху. Кликните по четвёртой слева (на ней изображены красные прямоугольники) и выберите BoxSizer, но сначала убедитесь в том, что объект на первом экране всё ещё выделен. Теперь, выбрав итем древа бокс сайзера, щёлкните по третей кнопке всплывающего окна и добавьте две кнопки в древо, называя их так, как показано. Сохраните вашу работу в файл twoBtns.xrc и у вас должен появиться файл, который выглядит так:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<?xml version="1.0" ?> <resource> <object class="wxFrame" name="MainFrame"> <object class="wxPanel" name="MainPanel"> <object class="wxBoxSizer"> <object class="sizeritem"> <object class="wxButton" name="okBtn"> <label>OK</label> </object> </object> <object class="sizeritem"> <object class="wxButton" name="cancelBtn"> <label>Cancel</label> </object> </object> <orient>wxHORIZONTAL</orient> </object> </object> </object> </resource> |
Это шокирует, но XRCed действительно выдаёт лёгкий для чтения XML-код. Теперь нам нужно выяснить как загрузить XML c помощью wxPython. К счастью, это достаточно просто. Смотрите:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import wx from wx import xrc class MyApp(wx.App): def OnInit(self): self.res = xrc.XmlResource("twoBtns.xrc") self.frame = self.res.LoadFrame(None, 'MainFrame') self.frame.Show() return True if __name__ == "__main__": app = MyApp(False) app.MainLoop() |
Для того, чтобы загрузить XML, нам нужно импортировать модуль xrc из wx. Затем мы загружаем XML со следующей строчкой: xrc.XmlResource(“twoBtns.xrc”). Учтите, что нам нужно попасть в имя (или путь) xrc-файла. Так что, вам придётся изменить то название, которое вы дали своей копии.
Чтобы загрузить рамку, мы вызываем метод объекта ресурса xml, который называется LoadFrame, пропуская его через None (к примеру no parent) и «имя, которое мы дали фрейму в xrc-файле». Здесь очень просто ошибиться. Вы ДОЛЖНЫ впечатать название виджета в код Python в точности, как вы сделали это в xrc-файле, иначе ничего не будет работать (или будет работать, но не так, как вы ожидаете). Кстати, название чувствительно к регистру. В любом случае, как только это сделано, вы делаете то, что вы обычно делаете в файле Python.
Создаём кое-что более сложное
Пример в прошлом разделе довольно хиленький. Давайте взглянем на то, как мы можем создать часть приложения в XRC, а вторую часть в wxPython. На скриншоте ниже изображён notebook с двумя секциями и PlateButton под ними. Notebook, фрейм и панель полностью сделаны в XRC, в то время как PlateButton – это просто обычный wx. Вот XML:
Пример в прошлом разделе довольно хиленький. Давайте взглянем на то, как мы можем создать часть приложения в XRC, а вторую часть в wxPython. На скриншоте ниже изображён notebook с двумя секциями и PlateButton под ними. Notebook, фрейм и панель полностью сделаны в XRC, в то время как PlateButton – это просто обычный wx. Вот XML:
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 |
<?xml version="1.0" ?> <resource> <object class="wxFrame" name="DemoFrame"> <object class="wxPanel" name="DemoPanel"> <object class="wxBoxSizer"> <orient>wxVERTICAL</orient> <object class="sizeritem"> <object class="wxNotebook" name="DemoNotebook"> <object class="notebookpage"> <object class="wxPanel" name="tabOne"/> <label>tabOne</label> </object> <object class="notebookpage"> <object class="wxPanel" name="tabTwo"/> <label>tabTwo</label> </object> </object> <option>1</option> <flag>wxALL|wxEXPAND</flag> <border>5</border> </object> </object> </object> <title>XRC Notebook Demo</title> </object> </resource> |
Теперь давайте добавим PlateButton:
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 |
import wx from wx import xrc import wx.lib.platebtn as platebtn class MyApp(wx.App): def OnInit(self): self.res = xrc.XmlResource("notebook.xrc") frame = self.res.LoadFrame(None, 'DemoFrame') panel = xrc.XRCCTRL(frame, "DemoPanel") notebook = xrc.XRCCTRL(panel, "DemoNotebook") sizer = wx.BoxSizer(wx.VERTICAL) btn = platebtn.PlateButton(panel, label="Test", style=platebtn.PB_STYLE_DEFAULT) btn.Bind(wx.EVT_BUTTON, self.onButton) sizer.Add(notebook, 1, wx.ALL|wx.EXPAND, 5) sizer.Add(btn) panel.SetSizer(sizer) frame.Show() return True def onButton(self, event): """""" print("You pressed the button!") if __name__ == "__main__": app = MyApp(False) app.MainLoop() |
Как вы видите это было также просто, как создавать приложения в чистом wxPython. Если бы здесь была wx.Button, определяемая в XRC, нам бы пришлось сделать то же самое, что мы делали с панелью, чтобы создать обработчика для неё. Как только у нас есть обработчик, мы можем привязывать события привычным способом.
Использование XRCed для генерирования кода Python
Приложение XRCed содержит генератор кода Python, который мы можем превратить в подкласс в нашем собственном коде. Для начала, мы используем первый простой пример из этой статьи, а затем расширим его, чтобы показать вам как привязывать события.
Запустите XRCed, загрузите в него первый пример, а затем нажмите File – GeneratePython. Согласитесь со всеми значениями по умолчанию и кликните по кнопке модуля Generate. Теперь у вас должно быть фрагмент автоматически сгенерированного кода, выглядящий вот так:
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 |
# This file was automatically generated by pywxrc. # -*- coding: UTF-8 -*- import wx import wx.xrc as xrc __res = None def get_resources(): """ Данная функция предоставляет доступ к ресурсам XML в данном модуле """ global __res if __res == None: __init_resources() return __res class xrcMainFrame(wx.Frame): #!XRCED:begin-block:xrcMainFrame.PreCreate def PreCreate(self, pre): """ Эта функция вызывается во время инициализации класса. Пропустите её для обычной установки до того, как было создано окно для того, чтобы, как правило, настраивать дополнительные стили окна, используя SetWindowStyle() и SetExtraStyl. """ pass #!XRCED:end-block:xrcMainFrame.PreCreate def __init__(self, parent): # Двухэтапное создание (Детальная информация: http://wiki.wxpython.org/index.cgi/TwoStageCreation) pre = wx.PreFrame() self.PreCreate(pre) get_resources().LoadOnFrame(pre, parent, "MainFrame") self.PostCreate(pre) # Определите переменные для контролей, забиндите хэндлеры событий # ------------------------ Данные о ресурсах ---------------------- def __init_resources(): global __res __res = xrc.EmptyXmlResource() __res.Load('twoBtns.xrc') |
Это немного коряво, но если вы можете прочесть обычный код wxPython, то и с этим разобраться должны. Теперь давайте создадим подкласс из этого кода. Почему мы это делаем? Таким образом мы можем изменить XRC-файл и последующий сгенерированный код и наш подкласс останется прежним. Это помогает нам отделять model (XML) от view (код wxPython).
Особое примечание: XRC пример, приведённый выше, не работает в wxPython Phoenix!
В любом случае, вот простой пример кода, который мы можем использовать с данным XRC примером в wxPython Classic.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# twoBtns_xrc_subclass.py import twoBtns_xrc import wx class XrcFrameSubClass(twoBtns_xrc.xrcMainFrame): """""" def __init__(self): """Constructor""" twoBtns_xrc.xrcMainFrame.__init__(self, parent=None) self.Show() if __name__ == "__main__": app = wx.App(False) frame = XrcFrameSubClass() app.MainLoop() |
Обратите внимание, что мы импортируем модуль “twoBtns_xrc”, который схож с тем, что я называю XRCfile. XRCed добавляет “_xrc” к названию файла Python. Как только импорт был произведён, мы может получить доступ к объекту XRC под названием Frame и превратить его в подкласс.
Итоги
Данная статья знакомит вас с азами использования приложения XRCed. Надеюсь, что вы узнали достаточно, чтобы применять его с умом и создавать действительно крутой код, используя эти «протоптанные дорожки». Если у вас возникли вопросы, то сначала ознакомьтесь с материалами Вики, задайте вопрос экспертам wxPython через электронную почту или просто поболтайте с ребятами на IRC-канале.
Являюсь администратором нескольких порталов по обучению языков программирования Python, Golang и Kotlin. В составе небольшой команды единомышленников, мы занимаемся популяризацией языков программирования на русскоязычную аудиторию. Большая часть статей была адаптирована нами на русский язык и распространяется бесплатно.
E-mail: vasile.buldumac@ati.utm.md
Образование
Universitatea Tehnică a Moldovei (utm.md)
- 2014 — 2018 Технический Университет Молдовы, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
- 2018 — 2020 Технический Университет Молдовы, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»