В предыдущей главе мы познакомились с методом bind виджетов, который использовался для перехвата нажатий кнопок. Так как метод bind часто используется вместе с другими виджетами (например, для перехвата нажатия клавиши Enter в полях ввода), остановимся на нем здесь в начале нашего обзора. Пример 8.15 иллюстрирует другие протоколы событий для метода bind.
Пример 8.15. PP4E\Gui\Tour\bind.py
from tkinter import *
def showPosEvent(event):
print(‘Widget=%s X=%s Y=%s’ % (event.widget, event.x, event.y))
def showAllEvent(event):
print(event)
for attr in dir(event):
if not attr.startswith(‘__’):
print(attr, ‘=>’, getattr(event, attr))
def onKeyPress(event):
print(‘Got key press:’, event.char)
def onArrowKey(event):
print(‘Got up arrow key press’)
def onReturnKey(event):
print(‘Got return key press’)
def onLeftClick(event):
print(‘Got left mouse button click:’, end=’ ‘)
showPosEvent(event)
def onRightClick(event):
print(‘Got right mouse button click:’, end=’ ‘)
showPosEvent(event)
def onMiddleClick(event):
print(‘Got middle mouse button click:’, end=’ ‘)
showPosEvent(event)
showAllEvent(event)
def onLeftDrag(event):
print(‘Got left mouse button drag:’, end=’ ‘)
showPosEvent(event)
def onDoubleLeftClick(event):
print(‘Got double left mouse click’, end=’ ‘)
showPosEvent(event)
tkroot.quit()
tkroot = Tk()
labelfont = (‘courier’, 20, ‘bold’) # семейство, размер, стиль
widget = Label(tkroot, text=’Hello bind world’)
widget.config(bg=’red’, font=labelfont) # красный фон, большой шрифт
widget.config(height=5, width=20) # начальн. размер: строк,символов
widget.pack(expand=YES, fill=BOTH)
widget.bind(‘<Button-1>’, onLeftClick) # щелчок мышью
widget.bind(‘<Button-3>’, onRightClick)
widget.bind(‘<Button-2>’, onMiddleClick) # средняя = обе на некот. мышах
widget.bind(‘<Double-1>’, onDoubleLeftClick)# двойной щелчок левой кнопкой
widget.bind(‘<B1-Motion>’, onLeftDrag) # щелчок левой кнопкой и перемещ
widget.bind(‘<KeyPress>’, onKeyPress) widget.bind(‘<Up>’, onArrowKey) widget.bind(‘<Return>’, onReturnKey) widget.focus()
tkroot.title(‘Click Me’) tkroot.mainloop()
Этот файл состоит в основном из функций обработчиков событий, вызываемых при возникновении связанных событий. Как было показано в главе 7, обработчики данного типа получают в качестве аргумента объект события, содержащий сведения о сгенерированном событии. Технически этот аргумент является экземпляром класса Event из библиотеки tkinter, и содержащиеся в нем подробности представлены атрибутами. Большинство обработчиков просто выводят информацию о событиях, извлекая значения из их атрибутов.
Если запустить этот сценарий, он создаст окно, изображенное на рис. 8.20. Главное его назначение — служить областью для запуска событий щелчков мышью и нажатия клавиш.
![]() |
|
Черно-белое издание, которое вы держите в руках, не позволяет оценить этот сценарий. При запуске вживую он использует приведенные выше настройки и выводит текст черным по красному большим шрифтом Courier. Вам придется поверить мне на слово (или запустить его самим).
Но главная задача этого примера — продемонстрировать действие других протоколов связывания событий. Мы уже встречали в главе 7 сценарий, который с помощью метода bind виджета и имен событий <Button-1> и <Double-1> перехватывал одиночные и двойные щелчки левой кнопкой мыши. Данный сценарий демонстрирует другие виды событий, часто перехватываемые с помощью метода bind:
<KeyPress>
Чтобы перехватывать нажатия одиночных клавиш на клавиатуре, можно зарегистрировать обработчик для события с идентификатором <KeyPress> — это более низкоуровневый способ ввода данных в программах с графическим интерфейсом, чем использование виджета Entry, о котором рассказывается в следующем разделе. Нажатая клавиша возвращается в виде кода ASCII в объекте события, передаваемом обработчику события (event.char). Другие атрибуты в структуре события позволяют идентифицировать нажатую клавишу на еще более низком уровне. Нажатия клавиш можно перехватывать виджетом корневого окна верхнего уровня или виджетом, которому передан фокус ввода с помощью метода focus, используемого в данном сценарии.
<B1-Motion>
Этот сценарий перехватывает также перемещение мыши при нажатой кнопке: зарегистрированный обработчик события <B1-Motion> вызывается всякий раз когда мышь передвигается при нажатой левой кнопке и получает в аргументе события текущие координаты X/Y указателя мыши (event.x, event.y). Эту информацию можно использовать для организации перемещения объектов, перетаскивания, рисования на уровне пикселей и так далее (смотрите демонстрационный пример программы PyDraw в главе 11).
<Button-3>, <Button-2>
Этот сценарий перехватывает также щелчки правой и средней кнопками мыши (называемыми также кнопками 3 и 2). Воспроизвести щелчок средней кнопкой 2 с помощью двухкнопочной мыши можно, щелкнув одновременно обеими кнопками, — если этот прием не действует, проверьте настройки мыши в интерфейсе свойств (Панель управления (Control Panel) в Windows)[XXXIV].
<Return>, <Up>
Чтобы перехватывать нажатия более специфических клавиш, в данном сценарии зарегистрированы обработчики событий нажатия клавиш Return/Enter и «стрелки вверх». В противном случае эти события были бы отправлены универсальному обработчику события <KeyPress> и потребовали бы дополнительного анализа события.
Ниже показано, что попадает в поток вывода stdout после щелчка левой кнопкой, правой кнопкой, левой кнопкой и перетаскивания, нескольких нажатий клавиш, нажатия клавиш Enter и «стрелки вверх» и наконец, двойного щелчка левой кнопкой для завершения. При нажатии левой кнопки мыши и перемещении курсора по экрану возникает множество сообщений с информацией о событии перетаскивания — одно сообщение выводится для каждого движения при перетаскивании (и для каждого производится вызов обработчика на языке Python):
C:\…\PP4E\Gui\Tour> python bind.py
Got left mouse button click: Widget=.25763696 X=376 Y=53
Got right mouse button click: Widget=.25763696 X=36 Y=60
Got left mouse |
button click |
: Widget=.25763696 X=144 Y=43 |
Got left mouse |
button drag: |
Widget=.25763696 X=144 Y=45 |
Got left mouse |
button drag: |
Widget=.25763696 X=144 Y=47 |
Got left mouse |
button drag: |
Widget=.25763696 X=145 Y=50 |
Got left mouse |
button drag: |
Widget=.25763696 X=146 Y=51 |
Got left mouse |
button drag: |
Widget=.25763696 X=149 Y=53 |
Got key press: s Got key press: p Got key press: a Got key press: m Got key press: 1 Got key press: — Got key press: 2 Got key press: . Got return key press Got up arrow key press Got left mouse button click: Widget=.25763696 X=300 Y=68 Got double left mouse click Widget=.25763696 X=300 Y=68
Для событий, связанных с мышью, обработчики выводят координаты X и Y указателя мыши, которые передаются в объекте события. Обычно координаты измеряются в пикселях от верхнего левого угла (0, 0), относительно того виджета, на котором произведен щелчок. Ниже показано, что выводится для щелчка левой кнопкой, средней кнопкой и двойного щелчка левой. Обратите внимание, что обработчик щелчка средней кнопкой выводит свой аргумент целиком — все атрибуты объекта Event (исключая внутренние атрибуты с именами, начинающимися с двух символов подчеркивания «__», в число которых входит атрибут __doc__ и методы перегрузки операторов, унаследованные от суперкласса object, подразумеваемого в Python 3.X по умолчанию). Различные типы событий устанавливают различные атрибуты. Например, нажатие большинства клавиш записывает некоторое значение в атрибут char:
C:\…\PP4E\Gui\Tour> python bind.py
Got left mouse button click: Widget=.25632624 X=6 Y=6
Got middle mouse button click: Widget=.25632624 X=212 Y=95 <tkinter.Event object at 0x018CA210> char => ?? delta => 0 height => ?? keycode => ??
keysym => ??
keysym_num => ??
num => 2
send_event => False
serial => 17
state => 0
time => 549707945
type => 4
widget => .25632624
width => ??
x => 212
x_root => 311
y => 95
y_root => 221
Got left mouse button click: Widget=.25632624 X=400 Y=183
Got double left mouse click Widget=.25632624 X=400 Y=183
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011