Python 3.8 / Tkinter:canvas 中的项不能从循环中绑定到函数



我不明白为什么这一小段代码适用于绿点(当我单击它时,显示的标签是可以的(,但对于红色的标签则完全不行(标签总是相同的,尽管循环:最新的一个(。

这是一个错误吗?还是我错过了什么?

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

按如下所示更改代码

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

问题出在绑定红色按钮事件canvas.tag_bind(p, '<Button-1>', lambda event: show(event, p, tag))的行中

在 lambda 中,您还必须传递参数p=p, tag=tag,如果不在回调中传递tag的引用并传递for loop中使用的p变量。这将导致每次更改该变量时,它们也会在回调函数中更改,并且它将生成您所看到的"error"。相反,如果您在labmda中设置变量,您将在回调处传递不会再次触及的新变量。

最新更新