Все графические интерфейсы, представленные до сих пор в этой книге, за исключением примера canvasDraw с непосредственным перемещением фигур, были довольно статичными. В данном, последнем разделе будет показано, как можно изменить эту ситуацию, добавив в пример 9.16 несколько простых анимаций перемещения фигуры на холсте.
Здесь также демонстрируется и расширяется понятие тегов холста — операции перемещения в этом примере применяются сразу ко всем объектам на холсте, связанным с тегом. Все овалы перемещаются при нажатии клавиши O, а все прямоугольники — при нажатии клавиши R. Как уже отмечалось ранее, методы холста принимают не только идентификаторы объектов, но и имена тегов.
Но главная задача сейчас состоит в том, чтобы проиллюстрировать простые приемы анимации с помощью инструментов, основанных на измерении интервалов времени и описанных выше в этом разделе. Существует три основных способа перемещения объектов по холсту:
• С помощью циклов, использующих функцию time.sleep для приостановки на доли секунды между последовательными операциями перемещения, наряду с вызовами метода update вручную. Сценарий выполняет перемещение, приостанавливается, передвигает объект еще немного и так далее. Функция time.sleep приостанавливает работу вызывающей программы и не возвращает управление в цикл событий графического интерфейса — обработка операций с интерфейсом, выполняемых во время перемещения, откладывается. Из- за этого после каждого перемещения нужно вызывать метод canvas. update, чтобы перерисовать экран, иначе экран не обновится, пока не закончится весь цикл перемещения в обработчике и не произойдет возврат. Это классический пример обработчика, выполняющегося продолжительное время. Без вызова метода обновления экрана вручную никакие другие события графического интерфейса не будут обработаны до возврата из обработчика (даже перерисовка окна).
• С помощью метода widget.after, планирующего выполнение операций перемещения через каждые несколько миллисекунд. Поскольку этот подход основан на расписании событий, которые библиотека tkinter отправляет обработчикам, он допускает параллельное осуществление нескольких перемещений и не требует вызова метода canvas.update. Для выполнения перемещений используется цикл событий, поэтому приостановка программы не требуется и графический интерфейс не блокируется.
• С помощью потоков выполнения, в которых выполняется несколько экземпляров циклов с приостановкой вызовом метода time.sleep, как в первом подходе. Так как потоки выполняются параллельно, приостановка любого из потоков не блокирует ни графический интерфейс, ни другие потоки, выполняющие перемещения. Как уже описывалось выше, графический нтерфейс вообще не следует обновлять из порожденных потоков, но некоторые методы холста, в частности метод move, в настоящее время допускают возможность вызова из потоков выполнения.
Из этих трех схем первая обеспечивает самое плавное воспроизведение анимации, но она замедляет другие операции во время перемещения. Вторая схема дает более замедленное перемещение, чем остальные, но в целом безопаснее, чем использование потоков выполнения, и обе последние схемы позволяют одновременно передвигать несколько объектов.
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011