For 循环中的 Tkinter 按钮命令 [英] Tkinter Button Commands in For Loop

查看:47
本文介绍了For 循环中的 Tkinter 按钮命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将 python 3 与 tkinter 一起使用,但我想从按钮执行的命令出现问题.生成了可变数量的按钮,每个访问者一个,我试图从按钮按下时调用函数 signOut,同时将相关项目(访问者)从列表中传递给它.

I am using python 3 with tkinter and I am having issues with a command I want to execute from a button. A variable number of buttons are generated, one for each visitor, and I am trying to call the function signOut from the button press whilst passing the relevent item (visitor) from the list to it.

我意识到问题在于 for 循环,因为在按下按钮时,i== 列表中的最后一项.我怎样才能使它特定于实际访问者.我似乎想不出解决办法.任何建议表示赞赏.

I realise that the issue is with the for loop as by the time the button is pressed, i will == the last item in the list. How can I make it specific to the actual visitor. I can't seem to think of the solution. Any advice is appreciated.

buttonDictionary = {}
for i in range(0,len(currentVisitors)):
    buttonDictionary[i] = Button(bottomFrame, text=currentVisitors[i], command=lambda: signOut(topFrame, bottomFrame, currentVisitors[i]))
    buttonDictionary[i].pack()

推荐答案

据我所知,例如i 在这样的循环中的 lambda 中是指变量 i 本身,而不是每次迭代时变量的值,因此当 command 回调被调用时,它会使用那个时刻 i 的值,正如你注意到的,这是最后一次迭代的值.

It is my understanding that e.g. i in a lambda within a loop like this is referring to the variable i itself, not the value of the variable on each iteration, so that when the command callback is called, it will use the value of i at that moment, which as you noticed is the value on the last iteration.

解决这个问题的一种方法是使用 partial.partial 实际上将冻结"循环中当前状态的参数,并在调用回调时使用这些参数.

One way to solve this is with a partial. partial will, in effect "freeze" the arguments at their current state in the loop and use those when calling the callback.

尝试使用 partial 而不是 lambda 像这样:

Try using a partial instead of a lambda like this:

from functools import partial

buttonDictionary = {}
for i in range(0,len(currentVisitors)):
    buttonDictionary[i] = Button(bottomFrame, text=currentVisitors[i], command=partial(signOut, topFrame, bottomFrame, currentVisitors[i]))
    buttonDictionary[i].pack()

另一种我见过但没有尝试过的方法是每次将 i 分配给 lambda 中的一个新变量:

Another way I have seen this done, but haven't tried, is to assign i to a new variable in your lambda each time:

command=lambda i=i: signOut(topFrame, bottomFrame, currentVisitors[i])

当我第一次在循环中使用 lambdas 开始使用 Python 时,我不止一次被烧坏(包括一个非常类似于尝试为循环中动态生成的按钮分配回调的情况).我什至创建了一个片段,每当我输入 lambda 时,它都会扩展为 think_about_it('你确定要使用 lambda 吗?') 只是为了提醒我我的痛苦导致自己...

I have gotten burned bad more than once when I first started with Python by using lambdas in loops (including a case very similar to this trying to assign a callback to dynamically generated buttons in a loop). I even created a snippet that would expand to think_about_it('are you sure you want to use a lambda?') whenever I typed lambda just to remind me of the pain I caused myself with that...

这篇关于For 循环中的 Tkinter 按钮命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆