События

Обычно, чтобы приложение с графическим интерфейсом что-то делало, должны происходить те или иные события, чаще всего представляющие собой воздействие человека на элементы GUI.

Можно выделить три основных типа событий: производимые мышью, нажатиями клавиш на клавиатуре, а также события, возникающие в результате изменения виджетов. Нередко обрабатываются сочетания. Например, клик мышью с зажатой клавишей на клавиатуре.

Типы событий

При вызове метода bind() событие передается в качестве первого аргумента.

Передача события в метод bind()

Название события заключается в кавычки, а также в угловые скобки < и >. События описывается с помощью зарезервированных последовательностей ключевых слов.

Часто используемые события, производимые мышью:

  • <Button-1> – клик левой кнопкой мыши

  • <Button-2> – клик средней кнопкой мыши

  • <Button-3> – клик правой кнопкой мыши

  • <Double-Button-1> – двойной клик левой кнопкой мыши

  • <Motion> – движение мыши

  • и т. д.

Пример:

from tkinter import *
 
def b1(event):
    root.title("Левая кнопка мыши")
def b3(event):
    root.title("Правая кнопка мыши")
def move(event):
    x = event.x
    y = event.y
    s = "Движение мышью {}x{}".format(x, y)
    root.title(s)
 
root = Tk()
root.minsize(width = 500, height=400)
 
root.bind('<Button-1>', b1)
root.bind('<Button-3>', b3)
root.bind('<Motion>', move)
 
root.mainloop() 

В этой программе меняется надпись в заголовке главного окна в зависимости от того, двигается мышь, щелкают левой или правой кнопкой.

Событие (event) – это один из объектов tkinter. У событий есть атрибуты, как и у многих других объектов. В примере в функции move() извлекаются значения атрибутов x и y объекта event, в которых хранятся координаты местоположения курсора мыши в пределах виджета, по отношению к которому было сгенерировано событие. В данном случае виджетом является главное окно, а событием – <Motion>, т. е. перемещение мыши.

Для событий с клавиатуры буквенные клавиши можно записывать без угловых скобок (например, 'a').

Для неалфавитных клавиш существуют специальные зарезервированные слова. Например, <Return> - нажатие клавиши Enter, <space>- пробел. (Заметим, что есть событие <Enter>, которое не имеет отношения к нажатию клавиши Enter, а происходит, когда курсор заходит в пределы виджета.)

Сочетания пишутся через тире. В случае использования так называемого модификатора, он указывается первым, детали на третьем месте. Например, <Shift-Up> - одновременное нажатие клавиш Shift и стрелки вверх, <Control-B1-Motion> – движение мышью с зажатой левой кнопкой и клавишей Ctrl.

from tkinter import *
 
def exitWin(event):
    root.destroy()
 
def inLabel(event):
    t = ent.get()
    lbl.configure(text = t)
 
def selectAll(event):
    root.after(10, select_all, event.widget)
def select_all(widget):
    widget.selection_range(0, END)
    widget.icursor(END) # курсор в конец
 
root = Tk()
 
ent = Entry(width=40)
ent.focus_set()
ent.pack()
lbl = Label(height=3, fg='orange', bg='darkgreen', font="Verdana 24")
lbl.pack(fill=X)
 
ent.bind('<Return>',inLabel)
ent.bind('<Control-a>',selectAll)
root.bind('<Control-q>',exitWin)
 
root.mainloop()

Пример программы, обрабатывающей события

Здесь сочетание клавиш Ctrl+a выделяет текст в поле. Без root.after() выделение не работает. Метод after() выполняет функцию, указанную во втором аргументе, через промежуток времени, указанный в первом аргументе. В третьем аргументе передается значение атрибута widget объекта event. В данном случае им будет поле ent. Именно оно будет передано как аргумент в функцию select_all() и присвоено параметру widget.

Практическая работа

Напишите программу по описанию. Размеры многострочного текстового поля определяются значениями, введенными в однострочные текстовые поля. Изменение размера происходит при нажатии мышью на кнопку, а также при нажатии клавиши Enter.

Цвет фона экземпляра Text светлосерый (lightgrey), когда поле не в фокусе, и белый, когда имеет фокус.

Событие получения фокуса обозначается как <FocusIn>, потери – как <FocusOut>.

Для справки: фокус перемещается по виджетам при нажатии Tab, Ctrl+Tab, Shift+Tab, а также при клике по ним мышью (к кнопкам последнее не относится).

GUI программы

Курс с примерами решений практических работ: android-приложение, pdf-версия.

Комментарии

Практическая работа.
from tkinter import *
 
def change1(event):
    t.config(width=int(e1.get()))
    t.config(height=int(e2.get()))
def change2():
    t.config(width=int(e1.get()))
    t.config(height=int(e2.get()))
def change_bg(event, b):
    t.config(bg=b)
 
root=Tk()
e1=Entry(width=5)
e2=Entry(width=5)
b=Button(text="Изменить", command=change2)
b.bind('<Return>', change1)
t=Text()
t.bind('<FocusIn>', lambda event, b="white": change_bg(event,b))
t.bind('<FocusOut>', lambda event, b="lightgrey": change_bg(event,b))
e1.grid(row=0, column=0, sticky=E)
e2.grid(row=1, column=0, sticky=E)
b.grid(row=0, column=1, rowspan=2, sticky=W)
t.grid(row=2, column=0, columnspan=2)
root.mainloop()

Где-то переделал и доработал
from tkinter import *
 
def change(event):
        try:
                t['width']=e1.get()
                t['height']=e2.get()
        except:
                t.insert(0.0, 'Uncorrect value\n')
 
def change2(event, b):
        t['bg']=b
 
root=Tk()
 
f0=Frame()
f0.pack()
f=Frame(f0)
f.pack(side=LEFT)
f1=Frame(f0)
f1.pack(side=LEFT)
 
e1=Entry(f, width=4)
e1.pack()
e2=Entry(f, width=4)
e2.pack()
b=Button(f1, width=10, text='Change')
b.bind('<Return>', change)
b.bind('<Button-1>', change)
b.pack(side=LEFT)
 
t=Text(width=20, height=10, bg='lightgrey')
t.bind('<FocusIn>', lambda event, b='white': change2(event, b))
t.bind('<FocusOut>', lambda event, b='lightgrey': change2(event, b))
t.pack()
 
root.mainloop()

from tkinter import  *
 
def bg_fin(event):
    text['bg'] = 'white'
def bg_fout(event):
    text['bg'] = 'lightgray'
def tw_change(event):
    a = e1.get()
    b = e2.get()
    if a and b != '':
        try:
            int(a) and int(b)
            text.delete(1.0, END)
            text['width'] = a
            text['height'] = b
        except:
            text.delete(1.0,END)
            text.insert(1.0,'Введите только цифры')
    else:
        text.delete(1.0, END)
        text.insert(0.0 , 'Введите два значение')
root= Tk()
fr1 = Frame(root)
fr2 = Frame(fr1)
fr1.pack(side = TOP)
fr2.pack(side = RIGHT)
 
e1 =Entry(fr1,width = 5)
e2 = Entry(fr1,width = 5)
b =Button(fr2,text = 'Изменить')
text = Text(bg = 'lightgray')
 
e1.pack(pady = 2)
e2.pack(pady = 2)
b.pack()
text.pack()
text.bind('<FocusIn>', bg_fin)
text.bind('<FocusOut>', bg_fout)
b.bind('<Button-1>', tw_change)
e1.bind('<Return>',tw_change)
e2.bind('<Return>',tw_change)
 
root.mainloop()