Tkinter 迭代按钮小部件错误

问题描述

所以我使用下面的代码名称和其他输入列表中迭代生成一大堆小部件。我现在的问题是按钮小部件,它们的所有命令都相同。代码的问题很明显,每个按钮的命令代码直到循环结束才会运行,因此所有按钮都调用与最后一个/“第 i 个”按钮相同的命令。

所以我的问题是如何让每个按钮调用正确的关联命令,而不是使用与最后一行中的按钮相同的命令,并且仍然迭代生成我的小部件。

# Generates a frame that also contains all the necessary widgets for all mounts in a list
# Takes the parent window the frame will be part of (TK()),# the row (int) and column (int) the new frame will be located on the parent window,# the name of the frame we're creating (string),# and a list of all the mounts to go into the frame (list of string),# the complement_checkBox (tkinter.CheckButton())
# Returns (tkinter.LabelFrame)
def generate_widgets(master,frame_name,mount_list,complement_checkBox):
    new_frame = LabelFrame(master,text = frame_name,font=("Arial Narrow",18),padx = 5,pady = 5)
    new_frame.grid(row = 0,column = 0,padx = 10,pady = 10,sticky = N + S + E + W)

    # We have row weight be equal to the number of mounts per frame
    master.rowconfigure(0,weight = len(mount_list))
    master.columnconfigure(0,weight = 1)

    label_widgets = {}
    attempts_string = {}
    spin_widgets = {}
    button_widgets = {}
    for i in range(len(mount_list)):

        full_name = mount_list[i]
        mount_name = full_name.split(' - ')[1]

        label_widgets[i] = Label(new_frame,text = mount_list[i],font = ("Arial Narrow",12))
        label_widgets[i].grid(row = i,sticky = W)

        attempts_string[i] = StringVar()
        attempts_string[i].set(load_attempts(mount_name))

        spin_widgets[i] = SpinBox(new_frame,from_ = 0,to = 255,width = 5,textvariable = attempts_string[i])
        spin_widgets[i].grid(row = i,column = 1,sticky = E)

        button_widgets[i] = Button(new_frame,text = "Calculate",command = lambda: open_and_save(full_name,mount_name,int(spin_widgets[i].get()),complement_checkBox.get()))
        button_widgets[i].grid(row = i,column = 2,sticky = E)

        new_frame.rowconfigure(i,weight = 1)

    # Column 0 is label,column 1 is spinBox,column 2 is button
    new_frame.columnconfigure(0,weight = 1)
    new_frame.columnconfigure(1,weight = 1)
    new_frame.columnconfigure(2,weight = 1)

    return new_frame

解决方法

对 lambda 使用默认参数,参见示例:

command = lambda f=full_name,m=mount_name:     open_and_save(f,m)
#                <-- default arguments -->   <- function definition ->

这个例子只使用了两个参数,但我认为你可以大致了解。

,

我最终使用了 command = lambda j = i,它在定义 lambda 的那一刻将 i 保存到 j,然后使用 j 作为 open_and_save 的输入