За исключением части, касающейся построения окружностей, программный код PyClock выглядит достаточно просто. Он рисует циферблат для отображения текущего времени и с помощью методов after вызывает себя 10 раз в секунду, проверяя, не перевалило ли системное время на следующую секунду. Если да, то перерисовываются секундная, минутная и часовая стрелки, чтобы показать новое время (либо изменяется текст меток цифровых часов). На языке создания графических интерфейсов это означает, что аналоговое изображение выводится на холсте, перерисовывается при изменении размеров окна и изменяется по запросу на цифровой формат.
В PyClock используется также стандартный модуль Python time, с помощью которого сценарий получает и преобразует системную информацию о времени в представление, необходимое для часов. В двух словах, метод onTimer получает системное время вызовом функции time.time, встроенного средства, возвращающего число с плавающей точкой, выражающее количество секунд, прошедших с начала эпохи, — точки начала отсчета времени на вашем компьютере. Затем с помощью функции time.localtime это время преобразуется в кортеж, содержащий значения часов, минут и секунд. Дополнительные подробности можно найти в самом сценарии и руководстве по библиотеке Python.
Проверка системного времени 10 раз в секунду может показаться излишней, но она гарантирует перемещение секундной стрелки вовремя и без рывков и скачков (события after синхронизируются не очень точно). На компьютерах, которыми я пользуюсь, это не влечет существенного потребления мощности ЦП. В Linux и в Windows PyClock незначительно расходует ресурсы процессора — в основном при обновлении экрана в аналоговом режиме, но не в событиях after.[51]
Чтобы минимизировать обновления экрана, PyClock перерисовывает только стрелки часов при переходе к следующей секунде — риски на циферблате перерисовываются только при начальном запуске и изменении размеров окна. На рис. 11.20 показан начальный циферблат PyClock в формате по умолчанию, который выводится при непосредственном запуске файла clock.py.
Рис. 11.20. Аналоговые часы PyClock по умолчанию
Линии, представляющие стрелки часов, имеют стрелку на одном конце, что определяется параметрами arrow и arrowshape объекта линии. Параметр arrow может принимать значение first, last, none или both; параметр arrowshape определяется как кортеж чисел, задающих длину стрелки на конце линии, общую длину линии и ее толщину.
Как и PyView, PyClock динамически удаляет и перерисовывает части изображения по требованию (то есть в ответ на связанные события) с помощью методов pack_forget и pack. Щелчок левой кнопкой мыши на часах изменяет формат вывода на цифровой путем удаления виджета аналоговых часов и вывода цифрового интерфейса. В результате получается более простой интерфейс, изображенный на рис. 11.21.
Рис. 11.21. Цифровые часы PyClock
Такая цифровая форма может пригодиться, если вы хотите сберечь драгоценное место на экране и уменьшить использование ЦП (расходы на обновление изображения этих часов очень малы). Следующий щелчок левой кнопкой на часах снова переводит их в аналоговый режим отображения. При запуске сценария конструируются оба отображения — аналоговое и цифровое, но в каждый отдельный момент прикреплено только одно из них.
Щелчок правой кнопкой мыши на часах в любом режиме отображения вызывает появление или исчезновение прикрепленной метки, показывающей текущую дату в простом текстовом формате. На рис. 11.22 показан аналоговый интерфейс PyClock с меткой даты и размещенной в центре фотографией (в таком виде часы запускаются из панели запуска PyLauncher).
Рис. 11.22. Улучшенный графический интерфейс PyClock с изображением
Изображение в центре на рис. 11.22 добавлено путем передачи объекта с соответствующими настройками конструктору объекта PyClock. Почти все особенности этого изображения могут быть настроены через атрибуты объектов PyClock — цвет стрелок, цвет меток, центральное изображение и начальный размер.
Так как сценарий PyClock в аналоговом режиме сам отображает фигуры на холсте, ему необходимо также самостоятельно обрабатывать события изменения размеров окна: когда окно уменьшается или увеличивается, нужно перерисовывать циферблат часов в соответствии с новыми размерами окна. Чтобы реагировать на изменение размеров окна, сценарий регистрирует событие <Configure> с помощью метода bind; удивительно, но это событие не является событием менеджера окон, как событие для кнопки закрытия. Если растянуть окно PyClock, циферблат увеличится вместе с окном, — попробуйте растянуть окно часов, сжать или распахнуть его во весь экран на своем компьютере. Так как циферблат строится в квадратной системе координат, окно PyClock всегда
растягивается в равном отношении по вертикали и горизонтали — если растянуть окно только по горизонтали или только по вертикали, циферблат не изменится.
В третьем издании этой книги в часы был добавлен таймер обратного отсчета: нажатие клавиши s или m выводит простой диалог ввода числа секунд или минут, соответственно, через которое должен сработать таймер. По истечении отсчета таймера выводится всплывающее окно, как показано на рис. 11.23, заполняющее весь экран в Windows. Я иногда использую этот таймер на курсах, которые я веду, — для напоминания мне и моим студентам, когда подходит время двигаться дальше (эффект получается особенно потрясающий, когда изображение экрана компьютера проецируется во всю стену!).
Рис. 11.23. Истек таймер PyClock
Наконец, подобно PyEdit, часы PyClock можно запускать автономно или прикреплять и встраивать их в другие графические интерфейсы, где требуется вывести текущее время. При автономном запуске повторно используется модуль windows из предыдущей главы (пример 10.16) — чтобы установить значок и заголовок окна, а также добавить вывод диалога подтверждения перед выходом. Для упрощения запуска часов, выполненных в заданном стиле, существует вспомогательный модуль clockStyles, предоставляющий ряд объектов с настройками, которые можно импортировать, расширять в подклассах и передавать конструктору часов. На рис. 11.24 показано несколько часов разных размеров и стилей, подготовленных заранее, ведущих синхронный отсчет времени.
Запустите сценарий clockstyles.py (или щелкните на кнопке PyClock в программе PyDemos, которая делает то же самое), чтобы воссоздать эту сцену с часами на своем компьютере. Во всех этих часах 10 раз в секунду проверяется изменение системного времени с использованием со-
Рис. 11.24. Несколько готовых стилей часов: clockstyles.py
бытий after. При выполнении в виде окон верхнего уровня в одном и том же процессе все они получают событие от таймера из одного и того же цикла событий. При запуске в качестве независимых программ в каждой из них имеется собственный цикл событий. В том и другом случае их секундные стрелки дружно перемещаются раз в секунду.
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011