How to stop event propagation in Python Tkinter?


Tkinter events are very powerful in handling the different objects and attributes of the widgets as well as the elements of an application. There are events such as mouse events and keyboard button events that can be handled by binding the event or callback function with the button.

Let us assume that we are creating an application that has two events of clicking the objects defined in a canvas widget. The two objects are basically the shapes (a rectangle and an oval) defined inside the canvas.

We can perform actions like the Button Click event to verify if the use clicked the rectangle or the oval. To perform this action, we can use the tag_bind(shape, "Button", callback) function which triggers the callback event whenever the button is clicked on a particular shape.

Example

The following example demonstrates the working of this application. Here, we have created two functions that will print whenever the user clicks on a particular shape.

# 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()

Output

Running the above code will display a window with two shapes (a rectangle and an oval). Clicking on each of the shapes will print the message on the main screen verifying which event has occurred.

On clicking the circle, you will get the following response −

You have clicked the oval

On clicking the rectangle, you will get the following response,

You have clicked the rectangle

However, on clicking the canvas, you will not get any response because we have set "event.widget.tag_click = False".

Example

Now, let's comment the event.widget.tag_click part in all the three functions. This is how the code would look like −

# 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()

Output

Now, when you click an object (let's say the rectangle object) on the canvas, it will raise an event and call rec_mouse_click(event), but it doesn't stop there. It will propagate the event further and call canvas_click(event). So, you will get the following output −

You have clicked the rectangle
You have clicked the Canvas

Updated on: 05-Sep-2023

220 Views

Kickstart Your Career

Get certified by completing the course

Get Started
Advertisements