首页 > 解决方案 > 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, column = 0, 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

标签: pythontkintertk

解决方案


我最终使用command = lambda j = i,它在定义 lambda 时将 i 保存到 j ,然后使用 j 作为open_and_save


推荐阅读