Skip to content
Advertisement

Suppressing other canvas items from reacting to event

I have a rectangle on a canvas listening for events, with a callback function “A”.

The blank space in the canvas is also listening to events with a callback function “B”.

When the I right-click on the rectangle, both “A” and “B” are executed. I understand why this happens (the rectangle is on the canvas).

The behavior I want to create is execution of “A” only when I right-click on the rectangle. How can I stop the empty canvas area from reacting to the event?

See the code below as an example of the behavior I currently have.

import tkinter as tk

window = tk.Tk()
window.geometry('500x500')
window.grid_rowconfigure(0, weight=1)
window.grid_columnconfigure(0, weight=1)

canvas = tk.Canvas(master=window)
canvas.grid(row=0, column=0, sticky='nsew')
canvas.bind('<Button-3>', lambda event: print('canvas right click'))

rectangle_id = canvas.create_rectangle(200, 200, 300, 300, fill='red')
canvas.tag_bind(rectangle_id, '<Button-3>', lambda event: print('rectangle right click'))

window.mainloop()

Advertisement

Answer

There is nothing built into tkinter that does this. In fact, the Canvas documentation specifically calls this out:

If bindings have been created for a canvas window using the bind command, then they are invoked in addition to bindings created for the canvas’s items using the bind widget command. The bindings for items will be invoked before any of the bindings for the window as a whole.

One workaround is to have your tag binding set some sort of flag to tell the canvas binding not to do any work.

Example:

import tkinter as tk

do_right_click = True

def canvas_right_click(event):
    global do_right_click
    if do_right_click:
        print("canvas right click")
    do_right_click = True

def element_right_click(event):
    global do_right_click
    do_right_click = False  # prevent canvas from processing this event
    print("rectangle right click")

window = tk.Tk()
window.geometry('500x500')
window.grid_rowconfigure(0, weight=1)
window.grid_columnconfigure(0, weight=1)

canvas = tk.Canvas(master=window)
canvas.grid(row=0, column=0, sticky='nsew')
canvas.bind('<Button-3>', canvas_right_click)

rectangle_id = canvas.create_rectangle(200, 200, 300, 300, fill='red')
canvas.tag_bind(rectangle_id, '<Button-3>', element_right_click)

window.mainloop()
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement