Reputation: 41
I cannot understand why this small piece of code works well for green points (when I click on it, displayed tags are OK) but not at all for red ones (tags are always the same although the loop : the latest one in).
Is it a bug? Or do I miss something?
import tkinter as tk
def show(event, p, tag):
print(f"{p=}\n{tag=}")
centers = [[50, 50], [90, 50]]
root = tk.Tk()
canvas = tk.Canvas()
canvas.grid(row=0, column=0, sticky='news')
p1 = canvas.create_oval(20,10,30,20, fill='green',tags=('point_green_1', 'draw'))
p2 = canvas.create_oval(50,10,60,20, fill='green',tags=('point_green_2', 'draw'))
canvas.tag_bind(p1, '<Button-1>', lambda event: show(event, p1, ('point_green_1', 'draw')))
canvas.tag_bind(p2, '<Button-1>', lambda event: show(event, p2, ('point_green_2', 'draw')))
for idx, center in enumerate(centers):
tag= f'point_{idx}'
p=canvas.create_oval(center[0] - 5, center[1] - 5, center[0] + 5, center[1] + 5, fill='red',
tags=(tag, 'draw'))
canvas.tag_bind(p, '<Button-1>', lambda event: show(event, p, tag))
root.mainloop()
Upvotes: 0
Views: 231
Reputation: 1429
Change the code as this
import tkinter as tk
def show(event, p, tag):
print(f"{p}\n{tag}")
centers = [[50, 50], [90, 50]]
root = tk.Tk()
canvas = tk.Canvas()
canvas.grid(row=0, column=0, sticky='news')
p1 = canvas.create_oval(20,10,30,20, fill='green',tags=('point_green_1', 'draw'))
p2 = canvas.create_oval(50,10,60,20, fill='green',tags=('point_green_2', 'draw'))
canvas.tag_bind(p1, '<Button-1>', lambda event: show(event, p1, ('point_green_1', 'draw')))
canvas.tag_bind(p2, '<Button-1>', lambda event: show(event, p2, ('point_green_2', 'draw')))
for idx, center in enumerate(centers):
tag= f'point_{idx}'
p=canvas.create_oval(center[0] - 5, center[1] - 5, center[0] + 5, center[1] + 5, fill='red', tags=(tag, 'draw'))
canvas.tag_bind(p, '<Button-1>', lambda event, p=p, tag=tag: show(event, p, tag))
root.mainloop()
The problem is in the line where you bind the red button event canvas.tag_bind(p, '<Button-1>', lambda event: show(event, p, tag))
at lambda you have to pass the args p=p, tag=tag
too, if not in the callback are passed the refereces of the tag
and p
variables that are used in the for loop
. This will cause that each time that you change that variables they will change in the callback functions too and it will generate the "error"
that you are seeing. Instead, if you set the varibles inside labmda
you will pass at the callback new variables that will not be touched again.
Upvotes: 2