属性仅分配给列表中的最后一个对象

时间:2016-02-26 14:47:24

标签: python tkinter

我正在尝试使用Tkinter在Python(2.7)中为PLC应用程序构建一个简单的GUI模拟器。我创建了一个带有许多标签的窗口,每个标签代表应用程序中的布尔位,我正在尝试将toggle函数绑定到每个标签对象,模拟PLC I / O的状态更改。为此,我建立了一个名为bits的列表,每个项目的字典看起来都像{'bit':'input1', 'value':True, 'type':'input'}

问题是我正在尝试将标签上的点击事件绑定到每个位的切换功能,但我的点击仅绑定到标签列表中的最后一个标签。

class Bitwin(tk.Frame):
def __init__(self, root):

    tk.Frame.__init__(self, root)
    self.canvas = tk.Canvas(root, borderwidth=0, background="#ffffff")
    self.frame = tk.Frame(self.canvas, background="#ffffff")
    self.canvas.pack(side="left", fill="both", expand=True)
    self.canvas.create_window((4,4), window=self.frame, anchor="nw", 
                              tags="self.frame")

    self.frame.bind("<Configure>", self.onFrameConfigure)

    self.labels=[]
    self.populate()

    for h,i in enumerate(self.labels):
        i.bind('<Button-1>', lambda event: toggle(i.cget('text')))
        i.grid(row=h%200, column=int(floor(h/200))+1)

def populate(self):
    for h,i in enumerate(bits):
        lab=tk.Label(self.frame, text=i['bit'], bg='grey',fg='white', width=20)
        self.labels.append(lab)

我认为在单独的循环中绑定toggle函数可以解决问题,但是没有。无论我点击哪个标签,只切换最后一个'位'。

1 个答案:

答案 0 :(得分:0)

因为i循环中lambdafor的绑定是懒惰的。定义lambda时,i不受约束,但是当它被调用时。{/ p>

您可以使用默认参数解决方法:

for h,i in enumerate(self.labels):
    i.bind('<Button-1>', lambda event, i=i: toggle(i.cget('text')))  # <--
    i.grid(row=h%200, column=int(floor(h/200))+1)