我已经看到了几种解决方案,用于将其他参数传递给以不同方式使用包装函数的Tkinter事件处理程序。但是对于在事件中传递一些额外静态数据的简单情况,这样做有任何缺点:
widget.my_private_attribute = my_private_data
并从事件处理程序中的事件中恢复数据:
private_data = event.widget.my_private_attribute
我已经尝试了它并且它有效,但它没有出现在我见过的任何建议的解决方案中所以我担心有一些我不知道的缺点。
这是一个代码示例。重新评论“私人”的含义,我猜这是误导。我的意思是“由我组成,而不是标准的tk属性之一”。
:
:
def onClickPosition(event):
print "you clicked on", event.widget.grid_position
if event.widget.cget("bg") == "red":
event.widget.config(bg="yellow")
else:
event.widget.config(bg="red")
root = tk.Tk()
buttonList = []
for i in range(16):
for j in range(16):
square = tk.PhotoImage(file="small_square_30x30pix.gif")
l = tk.Label(root, image=square, borderwidth=0, bg="yellow")
l.save_image = square
l.grid_position=(i,j)
l.bind("<1>", onClickPosition)
l.grid(row=i, column=j)
buttonList.append(l)
:
:
“grid_position”是我所指的数据。
我在解决方案上看到了几种变体:
http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/extra-args.html
但我这样做的方式似乎更简单。
答案 0 :(得分:1)
而不是:
l.grid_position=(i,j)
l.bind("<1>", onClickPosition)
...
def onClickPosition(event):
print "you clicked on", event.widget.grid_position
尝试:
l.bind("<1>", lambda event, i=i, j=j: onClickPosition(event, i, j))
...
def onClickPosition(event, i, j):
print "you clicked on", (i,j)
lambda
定义了一个内联匿名函数,允许我们向onClickPosition()
发送更多参数。将i=i, j=j
置于定义中会在定义函数时解析这些变量,而不是在调用函数时解析 - lambda event, i, j
将始终生成(15, 15)
的点击位置。
答案 1 :(得分:1)
它的价值“属于”任何有意义的小部件,然后是的,不仅将它作为属性附加是安全的,它是惯用的。
文档中有很多例子。
首先,使用子类Frame
的“标准Tkinter OO惯用法”在__init__
方法或其他地方添加属性的每个示例都正在完成您正在做的事情。你没有子类的事实是不相关的;这是一样的想法。
如果您不购买,请参阅Tkinter Book的PhotoImage
页面:
注意:当Python对垃圾收集PhotoImage对象时(例如,当您从一个将图像存储在局部变量中的函数返回时),即使Tkinter小部件正在显示该图像,该图像也会被清除。
为避免这种情况,程序必须对图像对象保留额外的引用。一种简单的方法是将图像分配给窗口小部件属性,如下所示:
label = Label(image=photo)
label.image = photo # keep a reference!
label.pack()
label
不是Label
的子类,它有另一个名为image
的属性,它只是一个Label
,我们刚刚动态添加了另一个属性,并且那很好。
这只是我在几秒钟内略读的第一个例子。
但也完全可以将值“分”回回调本身,就像在TigerhawkT3的回答中一样。 *
*事实上,我认为这是让Guido相信Python 3.x仍需要lambda
和partial
的论据之一。
那么,您如何决定使用哪一个?这是一个判断电话。以下是我对此的看法:
如果这些都没有帮助,那么,您最终需要一些默认策略来处理近距离判断调用。我喜欢以两种方式编写它,然后看看哪一个看起来更具可读性,或者想象一下向刚刚注册以帮助我维护代码的新手解释。如果我还是无法决定,我会在交互式解释器中键入random.random() < 0.5
。 :)子>