Несколько лет назад я написал туториал для wxPython 2.8. и его встроенного Pubsub модуля, который вы можете прочесть в моём блоге. Тогда же, новое API для Pubsub было добавлено в wxPython 2.8.11.0. Запустить его можно было с помощью этого кода:
1 2 |
import wx.lib.pubsub.setupkwargs from wx.lib.pubsub import pub |
Старый способ импорта Pubsub выглядел так:
1 |
from wx.lib.pubsub import Publisher |
Теперь в версии wxPython 2.9 и новее, он выглядит так:
1 |
from wx.lib.pubsub import pub |
Зачем я упоминаю всё это? Поскольку в интернете ещё можно встретить туториалы для wxPython 2.8, эта информация может оказаться полезной, а также есть люди, которые по каким-то причинам не хотят переходить на более новую версию.
Есть вопросы по Python?
На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!
Паблик VK
Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!
Модуль Pubsub в wxPython также распространяется и отдельно, так что вы можете без проблем добавить его к вашим собственным приложениям Python. Проще говоря, пакет Pubsub позволяет вам писать программы, которые следуют модели Publish/Subscribe. Основная идея в том, чтобы создать одного или несколько слушателей, известных также как подписчики. У подписчиков будет отображаться сообщение, которое вы распространяете через паблишер.
Текущая версия Pubsub API
Я считаю, что писать код по частям и проверять каждую из них – это отличная идея. Так что давайте напишем простой код, чтобы узнать, насколько хорошо вы поняли логику.
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 65 66 67 68 69 70 71 72 73 74 75 76 |
import wx from wx.lib.pubsub import pub class OtherFrame(wx.Frame): """""" def __init__(self): """Constructor""" wx.Frame.__init__(self, None, wx.ID_ANY, "Secondary Frame") panel = wx.Panel(self) msg = "Enter a Message to send to the main frame" instructions = wx.StaticText(panel, label=msg) self.msgTxt = wx.TextCtrl(panel, value="") closeBtn = wx.Button(panel, label="Send and Close") closeBtn.Bind(wx.EVT_BUTTON, self.onSendAndClose) sizer = wx.BoxSizer(wx.VERTICAL) flags = wx.ALL|wx.CENTER sizer.Add(instructions, 0, flags, 5) sizer.Add(self.msgTxt, 0, flags, 5) sizer.Add(closeBtn, 0, flags, 5) panel.SetSizer(sizer) def onSendAndClose(self, event): """ Отправить сообщение и закрыть фрейм """ msg = self.msgTxt.GetValue() pub.sendMessage("panelListener", message=msg) pub.sendMessage("panelListener", message="test2", arg2="2nd argument!") self.Close() class MyPanel(wx.Panel): """""" def __init__(self, parent): """Constructor""" wx.Panel.__init__(self, parent) pub.subscribe(self.myListener, "panelListener") btn = wx.Button(self, label="Open Frame") btn.Bind(wx.EVT_BUTTON, self.onOpenFrame) def myListener(self, message, arg2=None): """ функция слушателя """ print("Received the following message: " + message) if arg2: print("Received another arguments: " + str(arg2)) def onOpenFrame(self, event): """ Открывает вторичный фрейм """ frame = OtherFrame() frame.Show() class MyFrame(wx.Frame): """""" def __init__(self): """Constructor""" wx.Frame.__init__(self, None, title="New PubSub API Tutorial") panel = MyPanel(self) self.Show() if __name__ == "__main__": app = wx.App(False) frame = MyFrame() app.MainLoop() |
Как я уже говорил, импорт выглядит немного иначе. Позже мы увидим, что ещё изменилось. В классе панелей мы создаём слушателя следующим образом:
1 |
pub.subscribe(self.myListener, "panelListener") |
Метод myListener принимает один или несколько аргументов. В данном случае, мы настраиваем его таким образом, чтобы он всегда требовал один аргумент (сообщение) и опциональный аргумент (arg2). Затем мы переходим к классу OtherFrame, где нам нужно обратить внимание на метод onSendAndClose. В данном методе, вы можете увидеть, что он отправляет 2 сообщения:
1 2 3 4 |
msg = self.msgTxt.GetValue() pub.sendMessage("panelListener", message=msg) pub.sendMessage("panelListener", message="test2", arg2="2nd argument!") self.Close() |
Первый отправляет только требуемую информацию, в то время как второй отправляет оба аргумента. Вы заметите, что новое API требует явные аргументы с ключевыми словами. Если вы измените первую команду sendMessage на pub.sendMessage(“panelListener”, msg), то вы получите исключение TypeError.
Итоги
Сейчас вы уже ознакомились с азами использования Pubsub в ваших wxPython приложениях. Я хочу обратить внимание на то, что Pubsub не обладает потоковой безопасностью, так что имейте это в виду. Если вы применяете Pubsub в потоке, вам нужно будет использовать метод, обладающий потоковой безопасностью, такой как wx.CallAfter или wx.PostEvent, так как они позволят отправлять сообщения вашим слушателям, исключая вероятность появления в вашем коде странных ошибок. Я использую Pubsub во многих своих программах и считаю его достаточно полезным.
Являюсь администратором нескольких порталов по обучению языков программирования Python, Golang и Kotlin. В составе небольшой команды единомышленников, мы занимаемся популяризацией языков программирования на русскоязычную аудиторию. Большая часть статей была адаптирована нами на русский язык и распространяется бесплатно.
E-mail: vasile.buldumac@ati.utm.md
Образование
Universitatea Tehnică a Moldovei (utm.md)
- 2014 — 2018 Технический Университет Молдовы, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
- 2018 — 2020 Технический Университет Молдовы, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»