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