Туториал по wx.Timer — wxPython #45

wx.Timer позволяет разработчикам программного обеспечения запускать определённые фрагменты кода через определённые интервалы. В данной статье я рассмотрю несколько разных способов создания таймеров. Объекта таймера запускает свой собственный цикл события, который им и контролируется, при этом не вмешивается в главный цикл wxPython.

Простой таймер

Туториал по wx.Timer - wxPython #45Мой первый пример невероятно прост. В нём лишь одна кнопка, которой можно останавливать и запускать таймер. Давайте взглянем на код.

Как вы видите, я импортирую только два модуля: wx и time. Я использую модуль time для того, чтобы задать время, в которое будет запущено событие wx.Timer. Две главных вещи, на которые стоит обратить внимания – это как привязывать таймер к событию и к самому хэндлеру события.

Есть вопросы по Python?

На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!

Telegram Чат & Канал

Вступите в наш дружный чат по Python и начните общение с единомышленниками! Станьте частью большого сообщества!

Паблик VK

Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!

Для того, чтобы данный пример заработал, вам нужно привязать фрейм к событию таймера. Я пытался привязать сам таймер (например, используя self.timer.Bind), но он не сработал. Логично, что я обратился к Робину Дану, чтобы выяснить, что происходит. Он сказал, что, если перентом таймера является фрейм, фрейм будет единственным объектом, который получит событие таймера, и так будет до тех пор, пока вы не извлечёте wx.Timer и не используете (отмените) его метод Notify. Как по мне, звучит логично.

В любом случае, давайте взглянем на мой хэндлер события. В нём я захватывают ярлык кнопки и использую условное выражение if, чтобы решить хочу я запускать или останавливать таймер, ведь ярлык будет отличатся в зависимости от текущего состояния таймера. В данном случае я могу использовать лишь одну функцию, которая будет переключать состояние таймера и самой кнопки. Стоит обратить внимание на методы Start и Stoр. Они контролируют сам таймер.

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

Перед тем, как перейти к следующему примеру, давайте посмотрим, как можно переработать этот. У Робина Дана было несколько идей, так что я внедрил их в код, который вы можете найти ниже. Вы уже нашли отличия?

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

Использование нескольких таймеров

Туториал по wx.Timer - wxPython #45

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

Если честно, то второй пример практически идентичен первому. Главным различием является то, что здесь у нас две кнопки и две разных инстанции. Я решил устроить немного «показухи» и привязал обе кнопки к одному хэндлеру события.

Это, наверное, один из лучших моих трюков. Чтобы увидеть, какая из кнопок запускает событие, вы можете использовать метод GetEventObject этого же события. Затем вы можете прикрепить к кнопке ярлык. Если вы совсем жёсткий, вы заметите, что я могу превратить строчки 30 и 31 в эту комбинацию:

Я разбил его на две строки, чтобы вам было проще понять принцип работы. Я использовал что-то вроде деления стрингов, чтобы захватывать номер ярлыка кнопки, так что я смогу узнать какой таймер запустится или остановится. Затем моя программа вводит мои заготовленные IF-утверждения, в которых она проверяет номер ярлыка кнопки и номер таймера. Теперь вы также знаете, как запустить или остановить несколько таймеров одновременно.

И снова же, Робин Дан предложил мне лучший способ написания второго примера, и вот как это выглядело:

В __init__ я добавил словарь, который привязан к объектам кнопок.  Значениями словаря являются: номер таймера, объект таймера и количество секунд (технически – миллисекунд) между событиями таймера.

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

Итоги

На данный момент вы уже должны довольно уверенно справляться с wx.Timer, а также чётко понимать, в каком из ваших проектов он будет смотреться гармоничнее всего. Это отличный способ запустить определённое событие через определённый промежуток времени, а ещё он довольно надёжен.

Отличным примером использования является программа для электронной почты, в которой требовалось через определённый промежуток времени проверять наличие новых писем. Я настроил таймер на настолько короткие промежутки времени, что получал уведомление о получении письма в ту же секунду, когда оно приходило.