Python 3.x 将方法绑定到动态创建的标签

Python 3.x 将方法绑定到动态创建的标签,python-3.x,tkinter,Python 3.x,Tkinter,我有一个Tkinter框架,它基本上显示了一组缩略图,显示在标签小部件中。我需要动态创建标签,以适应不同数量的缩略图生成。我有一个生成的文件名列表,可以根据需要创建缩略图,但当我尝试将函数绑定到每个创建的标签时,它似乎被上次创建的标签/绑定所覆盖。结果是,只有最终标签绑定了方法 import tkinter as tk class test(tk.Tk): def __init__(self, *args, **kwargs): tk.Tk.__init__(self,

我有一个Tkinter框架,它基本上显示了一组缩略图,显示在标签小部件中。我需要动态创建标签,以适应不同数量的缩略图生成。我有一个生成的文件名列表,可以根据需要创建缩略图,但当我尝试将函数绑定到每个创建的标签时,它似乎被上次创建的标签/绑定所覆盖。结果是,只有最终标签绑定了方法

import tkinter as tk

class test(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args)
        self.shell = tk.Frame(self)
        self.shell.pack()
        self.create_widgets()


    def create_widgets(self):
        '''
        Two rows of labels
        '''
        for row in range(2):
            for i in range(5):
                text = 'Thumbnail\nrow{}\ncolumn{}'.format(row,i)
                self.thumb = tk.Label(self.shell,                                     
                                     text = text)
                self.thumb.grid(row = row, column = i, sticky = 'news')
                self.thumb.bind("<Button-1>",lambda x: self.click(self.thumb))

    def click(self, *args):
        #This should affect only the Label that was clicked
        print('CLICK!')



app = test()
root = app
root.mainloop()
将tkinter作为tk导入
类别测试(tk.tk):
定义初始化(self,*args,**kwargs):
tk.tk.\uuuu初始化(self,*args)
self.shell=tk.Frame(self)
self.shell.pack()
self.create_widgets()
def创建_小部件(自):
'''
两行标签
'''
对于范围(2)中的行:
对于范围(5)中的i:
text='Thumbnail\nrow{}\n列{}'。格式(行,i)
self.thumb=tk.Label(self.shell,
文本=文本)
self.thumb.grid(row=row,column=i,sticky=news)
self.thumb.bind(“,lambda x:self.click(self.thumb))
def单击(自身,*参数):
#这应该只影响单击的标签
打印('单击!')
app=test()
root=app
root.mainloop()

调用的方法将始终相同,但如何识别要生效的标签?

当您单击标签时,tk使用
事件对象运行函数,您可以使用
lambda x
跳过该函数

你需要

lambda event:self.click(event, ...)
然后在
中单击
,您可以使用
event.widget
获得单击的widget

def click(event, ...);

   print('Widget text:', event.widget['text'])

您在
self中的
self.thumb
有问题。单击(self.thumb)
,因为您不知道
for
循环中的
lambda
是如何工作的。(这是一个非常普遍的问题:))

lambda
“懒惰的”
。当您声明
lambda x:self.click(self.thumb)
时,它不会从
self.thumb
获取值,但当您单击按钮(并执行
lambda
)时,它会从
for
循环中获取值。但当您单击标签时,则
for
循环完成,并且
self.thumb
保留最后一个值

当您声明
lambda

labda event, t=self.thumb: self,clikc(t)

当您单击标签时,tk将使用
事件对象运行函数,您可以使用
lambda x
跳过该对象

你需要

lambda event:self.click(event, ...)
然后在
中单击
,您可以使用
event.widget
获得单击的widget

def click(event, ...);

   print('Widget text:', event.widget['text'])

您在
self中遇到了
self.thumb
问题。单击(self.thumb)
,因为您不知道
for
循环中的
lambda
是如何工作的。(这是一个非常常见的问题:)

lambda
“懒惰的”
。当您声明
lambda x:self.click(self.thumb)
时,它不会从
self.thumb
获取值,但当您单击按钮(并执行
lambda
)时,它会从
for
循环中获取值。但当您单击标签时,则
for
循环完成,并且
self.thumb
保留最后一个值

当您声明
lambda

labda event, t=self.thumb: self,clikc(t)

至少有三种解决方案

第一个是最简单的:向函数传递一个事件对象,该对象包含对小部件的引用:

label = tk.Label(...)
label.bind("<Button-1>", self.click)
...
def click(self, event):
    print("you clicked:", event.widget)
label=tk.label(…)
label.bind(“,self.click)
...
def单击(自身,事件):
打印(“您单击:”,event.widget)
如果您喜欢使用lambda,可以将标签本身传递给函数:

label = tk.Label(...)
label.grid(...)
label.bind("<Button-1>",lambda event, label=label: self.click(label))
self.labels = []
for row in range(2):
    for i in range(5):
        label = tk.Label(...)
        label.grid(...)
        self.labels.append(label)
        index = len(self.labels)
        label.bind("<Button-1>",lambda event, i=index: self.click(i))
...
def click(self, index):
    print("the label is ", self.labels[index])
label=tk.label(…)
label.grid(…)
label.bind(“”,lambda事件,label=label:self。单击(label))
另一种解决方案是保留对列表中每个标签的引用,并将索引传递给函数:

label = tk.Label(...)
label.grid(...)
label.bind("<Button-1>",lambda event, label=label: self.click(label))
self.labels = []
for row in range(2):
    for i in range(5):
        label = tk.Label(...)
        label.grid(...)
        self.labels.append(label)
        index = len(self.labels)
        label.bind("<Button-1>",lambda event, i=index: self.click(i))
...
def click(self, index):
    print("the label is ", self.labels[index])
self.labels=[]
对于范围(2)中的行:
对于范围(5)中的i:
label=tk.label(…)
label.grid(…)
self.labels.append(标签)
索引=长度(自标签)
label.bind(“”,lambda事件,i=index:self.click(i))
...
def单击(自我,索引):
打印(“标签为”,self.labels[索引])

至少有三种解决方案

第一个是最简单的:向函数传递一个事件对象,该对象包含对小部件的引用:

label = tk.Label(...)
label.bind("<Button-1>", self.click)
...
def click(self, event):
    print("you clicked:", event.widget)
label=tk.label(…)
label.bind(“,self.click)
...
def单击(自身,事件):
打印(“您单击:”,event.widget)
如果您喜欢使用lambda,可以将标签本身传递给函数:

label = tk.Label(...)
label.grid(...)
label.bind("<Button-1>",lambda event, label=label: self.click(label))
self.labels = []
for row in range(2):
    for i in range(5):
        label = tk.Label(...)
        label.grid(...)
        self.labels.append(label)
        index = len(self.labels)
        label.bind("<Button-1>",lambda event, i=index: self.click(i))
...
def click(self, index):
    print("the label is ", self.labels[index])
label=tk.label(…)
label.grid(…)
label.bind(“”,lambda事件,label=label:self。单击(label))
另一种解决方案是保留对列表中每个标签的引用,并将索引传递给函数:

label = tk.Label(...)
label.grid(...)
label.bind("<Button-1>",lambda event, label=label: self.click(label))
self.labels = []
for row in range(2):
    for i in range(5):
        label = tk.Label(...)
        label.grid(...)
        self.labels.append(label)
        index = len(self.labels)
        label.bind("<Button-1>",lambda event, i=index: self.click(i))
...
def click(self, index):
    print("the label is ", self.labels[index])
self.labels=[]
对于范围(2)中的行:
对于范围(5)中的i:
label=tk.label(…)
label.grid(…)
self.labels.append(标签)
索引=长度(自标签)
label.bind(“”,lambda事件,i=index:self.click(i))
...
def单击(自我,索引):
打印(“标签为”,self.labels[索引])

您的示例不起作用-您绑定了函数
self.test()
,但您只有
self.click()
。什么是
self.card
?对不起,我的原始代码编辑不好,现在修复了您的示例不起作用-您绑定了函数
self.test()
,但您只有
self.click()
。什么是
self.card
?很抱歉,我的原始代码编辑不好,现在修复得很好,非常感谢!Lambda对我来说仍然很滑!@Kelly:我已经更新了我的答案,说明了如何在没有Lambda的情况下使用Lambda。在我看来,只有当你需要使用Lambda时才应该使用Lambda,而且看起来你可能不需要使用Lambda。很多感谢,我正在使用lambda,因为我似乎需要在事件绑定中将小部件作为参数传递,看到其他工作方法总是很好!太好了,非常感谢!lambda仍然是