Инструменты синхронизации, потоки выполнения и анимация

instrumenty sinhronizacii potoki vypolneniya i animaciya Экскурсия по tkinter, часть 2

Последняя остановка в нашей экскурсии по виджетам, вероятно, самая необычная. Библиотека tkinter предоставляет ряд инструментов, которые связаны с моделью программирования, управляемого событиями, а не с отображением графики на экране.

Некоторым приложениям с графическим интерфейсом требуется периодически выполнять действия в фоновом режиме. Например, чтобы придать виджету «мерцающий» вид, можно зарегистрировать обработчик, который будет вызываться через равные промежутки времени. Аналогично при выполнении длительной операции с файлом неверно было бы заблокировать прочие действия в графическом интерфейсе — если бы удалось заставить цикл событий периодически выполнять обновления, графический интерфейс мог бы оставаться активным. В библиотеке tkinter есть средства для планирования таких отложенных действий и принудительного обновления интерфейса:

widget.after(milliseconds, function, *args)

Этот инструмент планирует вызов указанной функции по истечении заданного числа миллисекунд. Данная форма вызова не останавливает программу — функция обратного вызова будет запущена позднее из обычного цикла событий tkinter, а вызывающая программа продолжит свою работу как обычно и графический интерфейс останется активным, пока функция ожидает вызова. Как уже говорилось в главе 5, в отличие от объекта Timer из модуля threading, события widget.after распространяются в главном потоке выполнения графического интерфейса и потому могут выполнять в нем любые изменения.

Аргумент function может быть любым вызываемым объектом Python: функцией, связанным методом, lambda-выражением и так далее. Аргумент milliseconds определяет интервал времени в миллисекундах и является целым числом — если разделить значение этого аргумента на 1000, получится эквивалентное число секунд. Любые значения в кортеже args будут переданы функции function в виде позиционных аргументов.

На практике вместо отдельных аргументов можно использовать lambda-выражения, чтобы сделать связь аргументов с функцией более явной, но это не является обязательным. Когда в качестве функции передается связанный метод, он может получать дополнительную информацию из атрибутов объекта, а не из аргументов. Метод after возвращает идентификатор, который можно передать методу after_cancel, чтобы отменить вызов обработчика. Метод after используется очень часто, поэтому несколько ниже о нем будет рассказываться более подробно и с примерами.

widget.after(milliseconds)

Этот инструмент останавливает выполнение программы на заданное количество миллисекунд. Например, если передать в аргументе число 5000, программа будет приостановлена на 5 секунд. В сущности, это то же самое, что библиотечная функция Python time. sleep(seconds), и обе функции могут применяться для создания задержки при отображении (например, в анимационных программах, таких как PyDraw и более простых примерах ниже).

widget.after_idle(function, *args)

Этот инструмент планирует вызов указанной функции при отсутствии других событий, которые должны обрабатываться. То есть функция function становится обработчиком холостого времени, который вызывается, когда графический интерфейс не занят ничем другим.

widget.after_cancel(id)

Этот инструмент отменяет вызов обработчика, запланированный методом after до того, как он произойдет. Аргумент id — значение, возвращаемое методом after.

widget.update()

Этот инструмент вынуждает библиотеку tkinter обработать все ожидающие события, имеющиеся в очереди событий, в том числе изменение геометрии окна, а также обновление и перерисовку виджетов. Его можно периодически вызывать из долго выполняющегося обработчика, чтобы обновить экран и произвести те изменения, которые уже запросил ваш обработчик. Если этого не делать, произведенные обработчиком изменения появятся на экране только после выхода из него. На время работы обработчика, выполняющегося продолжительное время, интерфейс может вообще зависнуть, если не обновлять его вручную (обработчики не выполняются в отдельных потоках, о чем говорится в следующем разделе); окно даже не будет перерисовывать себя при перекрытии или открытии другими окнами, пока не произойдет возврат из обработчика.

Например, программы, осуществляющие анимацию путем последовательного перемещения объекта и приостановки, должны вызывать этот метод, не дожидаясь конца анимации, иначе на экране можно будет увидеть только конечное положение объекта. Что еще хуже, интерфейс окажется совершенно неактивным, пока не произойдет возврат из обработчика анимации (смотрите простые примеры воспроизведения анимации далее в этой главе и в программе PyDraw в главе 11).

widget.update_idletasks()

Этот инструмент запускает обработку всех событий холостого времени. Иногда он безопаснее, чем метод after, который в некоторых случаях может стать причиной возникновения состояния гонки за ресурсами (race conditions). События холостого времени используются виджетами Tk для отображения самих себя.

_tkinter.createfilehandler(file, mask, function)

Этот инструмент назначает функцию, которая будет вызываться при изменении состояния файла. Функция может быть вызвана, когда в файле появятся данные для чтения, когда он станет доступным для записи или когда будет возбуждено исключение. В аргументе file передается объект Python файла или сокета (формально — любой объект с методом fileno()) или целочисленный дескриптор файла; аргументе mask — значение tkinter.READABLE или tkinter.WRITABLE, определяющее режим; а в аргументе function передается функция обратного вызова, принимающая два аргумента — признак готовности файла к выполнению операции и маску. Обработчики файлов часто используются для обработки каналов и сокетов, так как обычные функции ввода/вывода могут блокировать вызывающую программу.

Этот метод недоступен в Windows и потому не будет рассматриваться в данной книге. Поскольку он доступен только в Unix, для разработки переносимых графических интерфейсов лучше использовать циклы таймера after для проверки готовности к выполнению операции и порождать потоки выполнения, которые будут читать данные и помещать их в очередь при необходимости; более подробно этот прием описывается в главе 10. Потоки выполнения являются более универсальным механизмом выполнения неблокирующих операций передачи данных.

widget.wait_variable(var)

widget.wait_window(win)

widget.wait_visibility(win)

Эти инструменты приостанавливают выполнение вызвавшей программы до момента, когда переменная tkinter изменит свое значение, будет разрушено окно или окно станет видимым. Все они входят в локальный цикл событий, благодаря чему функция mainloop приложения продолжает обработку событий. Обратите внимание, что аргумент var является объектом переменной tkinter (о которых рассказывалось ранее), а не простой переменной Python. Для использования в модальных диалогах сначала следует вызвать widget.focus() (чтобы установить фокус ввода) и widget.grab() (чтобы сделать окно единственным активным).

Некоторые из этих инструментов мы будем использовать в примерах, но не станем вникать во все их особенности здесь. За дополнительной информацией обращайтесь к другой документации по библиотекам Tk и tkinter.

Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011

Оцените статью
Секреты программирования
Добавить комментарий