Глава 17 · Финальные штрихи
Visual effects и after()
Один короткий, неблокирующий эффект — победа должна быть замечена, а не устроить дискотеку.
Один ненавязчивый эффект — не фреймворк анимации
После победы клетки выигрышной линии один раз получают мягкий акцент и спокойно
возвращаются к постоянной подсветке. На реальном окне это выглядит как краткий переход
между accent-состоянием и базовой подсветкой победы; сайт не может показать
видео-анимацию, поэтому ниже — реальные кадры этого перехода, а локальное приложение
переключает их через after(). Различимых кадров всего два:
третий снимок совпадает со вторым не случайно — эффект заканчивается именно на постоянной
подсветке победы и дальше ничего не меняет.
Эффект намеренно сдержанный — никакого резкого высококонтрастного мигания.
pulse_winning_line.py
def pulse_winning_line(self, tick=0):
if not self.state.winning_line:
return
color = PULSE_BG if tick == 0 else WIN_BG
for index in self.state.winning_line:
self.buttons[index].config(bg=color)
if tick == 0:
self._pulse_job = self.root.after(400, self.pulse_winning_line, 1)
else:
self._pulse_job = None
Самопланирующийся after() — знакомый приём из главы 16
Та же техника self-rescheduling, что и в разделе 16.22: каждый вызов
pulse_winning_line сам планирует свой следующий тик через after(), пока не достигнет предела — событийный цикл ни на миг не блокируется.Отменяйте запланированный after() при новом раунде
Если игрок нажимает «Новый раунд» посреди анимации, недоделанный
after() может сработать уже на пустом поле нового раунда. cancel_pulse() вызывает after_cancel() перед сбросом — та же дисциплина трёх состояний, что и у таймера в разделе 16.28.cancel_pulse.py
def cancel_pulse(self):
if self._pulse_job is not None:
self.root.after_cancel(self._pulse_job)
self._pulse_job = None
Никакого time.sleep(): один спокойный переход
Эффект не мигает серией: линия получает мягкий accent-цвет и через 400 мс остаётся в постоянной подсветке победы. Даже короткие эффекты должны быть ненавязчивыми и не отвлекать от статуса «Победил игрок X/O». Для продукта с формальными требованиями доступности параметры и возможность отключения эффектов проверяют отдельно.
Практика: ненавязчивая анимация победы
Модуль tkinter открывает нативное окно Python — выполните локально в VS Code, PyCharm или Jupyter
Практика выполняется локально