Глава 17 · События глубже

Focus и клавиатура

Окно существует — не значит, что оно получает все нажатия клавиш. Нужен фокус.

Клавиатурным событиям нужен адресат

Окно, в котором есть привязка к клавише, не значит, что нажатие ЛЮБОЙ клавиши где угодно попадёт в этот обработчик. Каждое клавиатурное событие сначала приходит в виджет, у которого сейчас фокус ввода — а уже оттуда Tk проверяет привязки по цепочке bindtags: сам виджет → его класс → окно верхнего уровня (root) → "all".

focus_demo.py
print(root.focus_get())   # какой виджет сейчас в фокусе (или None)

entry.focus_set()         # явно передать фокус этому виджету
«Привязка не работает» часто означает «класс виджета перехватил событие раньше»
root.bind("<Key>", ...) стоит в цепочке ПОСЛЕ привязок самого сфокусированного виджета и его класса — не вместо них. Если фокус на поле ввода, класс Entry первым обрабатывает нажатие цифры (вписывает символ в поле); привязка на root при этом обычно ВСЁ РАВНО срабатывает следом, если только обработчик явно не вернул "break", прервав цепочку. Значит символ и появится в поле ввода, И одновременно уйдёт в игровую логику — редко то, чего вы хотели. Смотрите Debug Lab 1 (раздел 17.29).

Для главы 17 клавиатурные привязки повешены на root — но, как только что было показано, фокус на Entry или Text сам по себе НЕ отключает привязку на root (у нашей игры таких полей нет — все клетки это кнопки). В приложении с текстовыми полями важно не «удерживать фокус на root», а осознанно решить: должны ли игровые горячие клавиши работать, пока пользователь печатает текст? Если нет — обработчик может проверить focus_get() и сам проигнорировать нажатие, когда фокус находится на текстовом поле.

Практика: focus_get() и focus_set()
Модуль tkinter открывает нативное окно Python — выполните локально в VS Code, PyCharm или Jupyter
Практика выполняется локально
Открыть практику →