Метод bind в Tkinter
В tkinter
с помощью метода bind
между собой связываются виджет, событие и действие. Например, виджет – кнопка, событие – клик по ней левой кнопкой мыши, действие – отправка сообщения. Другой пример: виджет – текстовое поле, событие – нажатие Enter, действие – получение текста из поля методом get
для последующей обработки программой. Действие оформляют как функцию или метод, которые вызываются при наступлении события.
Один и тот же виджет можно связать с несколькими событиями. В примере ниже используется одна и та же функция-обработчик, однако могут быть и разные:
from tkinter import * root = Tk() def change(event): b['fg'] = 'red' b['activeforeground'] = 'red' b = Button(text='RED', width=10, height=3) b.bind('<Button-1>', change) b.bind('<Return>', change) b.pack() root.mainloop()
Здесь цвет текста на кнопке меняется как при клике по ней (событие <Button-1>
), так и при нажатии клавиши Enter (событие <Return>
). Однако Enter сработает, только если кнопка предварительно получила фокус. В данном случае для этого надо один раз нажать клавишу Tab. Иначе нажатие Enter будет относиться к окну, но не к кнопке.
У функций-обработчиков, которые вызываются через bind
, а не через свойство command
, должен быть обязательный параметр event, через который передается событие. Имя event – соглашение, идентификатор может иметь другое имя, но обязательно должен стоять на первом месте в функции, или может быть вторым в методе:
from tkinter import * root = Tk() class RedButton: def __init__(self): self.b = Button(text='RED', width=10, height=3) self.b.bind('<Button-1>', self.change) self.b.pack() def change(self, event): self.b['fg'] = 'red' self.b['activeforeground'] = 'red' RedButton() root.mainloop()
Что делать, если в функцию надо передать дополнительные аргументы? Например, клик левой кнопкой мыши по метке устанавливает для нее один шрифт, а клик правой кнопкой мыши – другой. Можно написать две разные функции:
from tkinter import * root = Tk() def font1(event): l['font'] = 'Verdana' def font2(event): l['font'] = 'Times' l = Label(text='Hello World') l.bind('<Button-1>', font1) # ЛКМ l.bind('<Button-3>', font2) # ПКМ l.pack() root.mainloop()
Но это не совсем правильно, так как код тела функций фактически идентичен, а имя шрифта можно передавать как аргумент. Лучше определить одну функцию:
def change_font(event, font): l['font'] = font
Однако возникает проблема, как передать дополнительный аргумент функции в метод bind
? Ведь в этот метод мы передаем объект-функцию, но не вызываем ее. Нельзя написать l.bind('<Button-1>', change_font(event, "Verdana"))
. Потому что как только вы поставили после имени функции скобки, значит вызвали ее, то есть заставили тело функции выполниться. Если в функции нет оператора return
, то она возвращает None
. Поэтому получается, что даже если правильно передать аргументы, то в метод bind
попадет None
, но не объект-функция.
На помощь приходят так называемые анонимные объекты-функции Python, которые создаются инструкцией lambda
. Применительно к нашей программе выглядеть это будет так:
l.bind('<Button-1>', lambda e, f='Verdana': change_font(e, f)) l.bind('<Button-3>', lambda e, f='Times': change_font(e, f))
Лямбда-функции можно использовать не только с методом bind
, но и опцией command
, имеющейся у ряда виджет. Если функция передается через command
, ей не нужен параметр event. Здесь обрабатывается только одно основное событие для виджета – клик левой кнопкой мыши.
У меток нет command
, однако это свойство есть у кнопок:
from tkinter import * def change_font(font): label['font'] = font root = Tk() label = Label(text='Hello World') label.pack() Button(command=lambda f='Verdana': change_font(f)).pack() Button(command=lambda f='Times': change_font(f)).pack() root.mainloop()
Практическая работа
Напишите программу по следующему описанию. Нажатие Enter в однострочном текстовом поле приводит к перемещению текста из него в список (экземпляр Listbox
). При двойном клике (<Double-Button-1>
) по элементу-строке списка, она должна копироваться в текстовое поле.
Курс с примерами решений практических работ: pdf-версия