Как остановить распространение событий в Python Tkinter?
События Tkinter очень эффективны при обработке различных объектов и атрибутов виджетов, а также элементов приложения. Существуют такие события, как события мыши и события кнопок клавиатуры, которые можно обрабатывать, привязав событие или функцию обратного вызова к кнопке.
Предположим, мы создаем приложение, которое имеет два события щелчка по объектам, определенным в виджете холста. По сути, эти два объекта представляют собой фигуры (прямоугольник и овал), определенные внутри холста.
Мы можем выполнять такие действия, как событие «Нажатие кнопки», чтобы проверить, щелкнул ли пользователь по прямоугольнику или овалу. Чтобы выполнить это действие, мы можем использовать функцию tag_bind(shape, «Button», callback), которая запускает событие обратного вызова при каждом нажатии кнопки на определенной фигуре.
Пример
Следующий пример демонстрирует работу этого приложения. Здесь мы создали две функции, которые будут выводиться всякий раз, когда пользователь нажимает на определенную фигуру.
# Import the required libraries
from tkinter import *
# Create an instance of tkinter frame or window
win = Tk()
# Set the size of the window
win.geometry("700x350")
def oval_mouse_click(event):
event.widget.tag_click = True
print("You have clicked the oval")
def rec_mouse_click(event):
event.widget.tag_click=True
print("You have clicked the rectangle")
def canvas_click(event):
if event.widget.tag_click:
event.widget.tag_click = False
return
# Create a canvas widget
canvas = Canvas(win)
# Create an oval inside the canvas
oval = canvas.create_oval(500 / 2 - 10, 400 / 2 - 10, 500 / 2 + 10, 400 / 2 + 10, fill='red')
# Create a rectangle inside the canvas
rectangle = canvas.create_rectangle(50, 0, 100, 50, fill='blue')
canvas.tag_bind(oval, "<Button-1>", oval_mouse_click)
canvas.tag_bind(rectangle, "<Button-1>", rec_mouse_click)
canvas.bind("<Button-1>", canvas_click)
canvas.pack()
win.mainloop()
Выход
Запуск приведенного выше кода отобразит окно с двумя фигурами (прямоугольник и овал). При нажатии на каждую из фигур на главном экране будет распечатано сообщение, проверяющее, какое событие произошло.
Нажав на кружок, вы получите следующий ответ —
You have clicked the oval
Нажав на прямоугольник, вы получите следующий ответ:
You have clicked the rectangle
Однако, щелкнув холст, вы не получите никакого ответа, поскольку мы установили "event.widget.tag_click=False".
Пример
Теперь давайте прокомментируем часть event.widget.tag_click во всех трех функциях. Вот как будет выглядеть код —
# Import the required libraries
from tkinter import *
# Create an instance of tkinter frame or window
win = Tk()
# Set the size of the window
win.geometry("700x350")
def oval_mouse_click(event):
# event.widget.tag_click = True
print("You have clicked the oval")
def rec_mouse_click(event):
# event.widget.tag_click=True
print("You have clicked the rectangle")
def canvas_click(event):
# if event.widget.tag_click:
# event.widget.tag_click = False
# return
print ("You have clicked the Canvas")
# Create a canvas widget
canvas = Canvas(win)
# Create an oval inside the canvas
oval = canvas.create_oval(500 / 2 - 10, 400 / 2 - 10, 500 / 2 + 10, 400 / 2 + 10, fill='red')
# Create a rectangle inside the canvas
rectangle = canvas.create_rectangle(50, 0, 100, 50, fill='blue')
canvas.tag_bind(oval, "<Button-1>", oval_mouse_click)
canvas.tag_bind(rectangle, "<Button-1>", rec_mouse_click)
canvas.bind("<Button-1>", canvas_click)
canvas.pack()
win.mainloop()
Выход
Теперь, когда вы щелкаете объект (скажем, прямоугольный объект) на холсте, он генерирует событие и вызывает rec_mouse_click(event), но на этом не останавливается. Он распространит событие дальше и вызовет canvas_click(event). Итак, вы получите следующий результат —
You have clicked the rectangle
You have clicked the Canvas