Tkinter позволяет обрабатывать события виджетов. Для обработки распространенных и наболее используемых событий Tkinter предоставляет интерфейс команд.
Например, для обработки нажатия на кнопку ее параметру command
надо передать функцию, которая будет вызываться при нажатии на кнопку
def click(): print("Hello") btn = ttk.Button(text="Click", command=click)
Ряд виджетов также позволяют с помощью параметра command задать обработчик для одного из событий данного виджета.
Однако что, если мы хотим обрабатывать другие события виджета. Например, для кнопки обработать получение фокуса, или обработать нажатие клавиши клавиатуры? Для подобных ситуаций Tkinter предоставляет ряд встроенных событий. Наиболее распространенные из них:
Activate
: окно становится активным.
Deactivate
: окно становится неактивным.
MouseWheel
: прокрутка колеса мыши.
KeyPress
: нажатие клавиши на клавиатуре.
KeyRelease
: освобождение нажатой клавиши
ButtonPress
: нажатие кнопки мыши.
ButtonRelease
: освобождение кнопки мыши.
Motion
: движение мыши.
Configure
: изменение размера и положения виджета
Destroy
: удаление виджета
FocusIn
: получение фокуса
FocusOut
: потеря фокуса.
Enter
: указатель мыши вошел в пределы виджета.
Leave
: указатель мыши покинул виджет.
Для привязки события к виджету применяется метод bind():
bind(событие, функция)
В качестве первого параметра указывается обрабатываемое событие, а в качестве второго - функция, которая обрабатывает событие.
Например, обработаем события получения и потери фокуса для кнопки:
from tkinter import * from tkinter import ttk root = Tk() root.title("METANIT.COM") root.geometry("250x200") def entered(event): btn["text"] ="Entered" def left(event): btn["text"] ="Left" btn = ttk.Button(text="Click") btn.pack(anchor=CENTER, expand=1) btn.bind("<Enter>", entered) btn.bind("<Leave>", left) root.mainloop()
Название событие передается в угловных скобках, например, "<Enter>" или "<Leave>". Для события Enter (получение фокуса) определен обработчик-функция entered, которая изменяет текст кнопки:
def entered(event): btn["text"] ="Entered"
Стоит обратить внимание, что функция обработки события должна принимать в качестве параметра объект события - в примере выше параметр event, даже если он в самой функции не используется.
Событие потери фокуса связывыется с функцией left:
btn.bind("<Leave>", left)
Кроме обычных событий некоторые виджеты Tkinter могут использовать виртуальные события или высокоуровневые события (выше были описаны низкоуровневые события), которые помещаются в двойные угловные скобки, например, событие выделения списка "<<ListboxSelect>>". Наиболее используемые виртуальные события будут рассмотрены в соответствующих темах про виджеты.
В примере выше при привязке события указывалось только имя события например, "<Enter>" или "<Leave>". Но в реальности в угловых скобках указывается не просто имя события, а его шаблон. Шаблон события имеет следующую форму:
<модификатор-имя_события-клавиша>
Часто используемые модификаторы:
Alt
: нажата клавиша AltControl
: нажата клавиша CtrlShift
: нажата клавиша ShiftAny
: нажата любая клавишаТакже в шаблоне можно указать конкретные клавиши или комбинации. Некоторые из них:
Alt_L
: левая клавиша alt
Alt_R
: правая клавиша alt
BackSpace
: клавиша backspace
Cancel
: клавиша break
Caps_Lock
клавиша CapsLock
Control_L
: левая клавиша control
Control_R
: правая клавиша control
Delete
: клавиша Delete
Down
: клавиша ↓
End
: клавиша end
Escape
: клавиша esc
Execute
: клавиша SysReq
F1
: клавиша F1
F2
: клавиша F2
Fi
: функциональная клавиша Fi
F12
: клавиша F12
Home
: клавиша home
Insert
: клавиша insert
Left
: клавиша ←
Linefeed
: клавиша Linefeed (control-J)
KP_0
: клавиша 0
KP_1
: клавиша 1
KP_2
: клавиша 2
KP_3
: клавиша 3
KP_4
: клавиша 4
KP_5
: клавиша 5
KP_6
: клавиша 6
KP_7
: клавиша 7
KP_8
: клавиша 8
KP_9
: клавиша 9
KP_Add
: клавиша +
KP_Begin
: центральная клавиша (5)
KP_Decimal
: клавиша точка (.
)
KP_Delete
: клавиша delete
KP_Divide
: клавиша /
KP_Down
: клавиша ↓
KP_End
: клавиша end
KP_Enter
: клавиша enter
KP_Home
: клавиша home
KP_Insert
: клавиша insert
KP_Left
: клавиша ←
KP_Multiply
: клавиша ×
KP_Next
: клавиша PageDown
KP_Prior
: клавиша PageUp
KP_Right
: клавиша →
KP_Subtract
: клавиша -
KP_Up
: клавиша ↑
Next
: клавиша PageDown
Num_Lock
: клавиша NumLock
Pause
: клавиша pause
Print
: клавиша PrintScrn
Prior
: клавиша PageUp
Return
: клавиша Enter
Right
: клавиша →
Scroll_Lock
: клавиша ScrollLock
Shift_L
: левая клавиша shift
Shift_R
: правая клавиша shift
Tab
: клавиша tab
Например
from tkinter import * from tkinter import ttk root = Tk() root.title("METANIT.COM") root.geometry("250x200") def single_click(event): btn["text"] ="Single Click" def double_click(event): btn["text"] ="Double Click" btn = ttk.Button(text="Click") btn.pack(anchor=CENTER, expand=1) btn.bind("<ButtonPress-1>", single_click) btn.bind("<Double-ButtonPress-1>", double_click) root.mainloop()
Здесь в шаблоне "<ButtonPress-1>" ButtonPress
- название события - нажатие кнопки мыши, а "1" указывает на конкретную кнопку - левую кнопку мыши (например, 3 - представляет правую кнопку)
А в шаблоне "<Double-ButtonPress-1>" добавляется модификатор Doubles
, который указывает на двойное нажатие.
В примерах выше обработка события устанавливалась для одного конкретного объекта - для одной кнопки. Но что, если у нас много кнопок и мы хотим, чтобы для всех была установлена привязка одного и тоже события с одной и той же функцией_обработчиком? В этом случае мы можем установить привязку события глобально ко всем объектам класса с помощью метода bind_class класса Tk:
from tkinter import * from tkinter import ttk clicks = 0 root = Tk() root.title("METANIT.COM") root.geometry("250x200") def clicked(event): global clicks clicks = clicks + 1 btn["text"] =f"{clicks} Clicks" btn = ttk.Button(text="Click") btn.pack(anchor=CENTER, expand=1) # привязка события к кнопкам ttk.Button root.bind_class("TButton", "<Double-ButtonPress-1>", clicked) root.mainloop()
В данном случае для кнопок для обработки двойного нажатия установаливается обработчик - функция clicked. Причем события привязывается к кнопкам из пакета tkinter.ttk, поэтому в качестве типа виджетов используется "TButton" (а не просто Button).
Для открепления события от виджета вызывается метод unbind(), в который передается шаблон события:
widget.unbind(event)