首页 > 解决方案 > 在循环中实例化时,Checkbutton 命令绑定到错误的值

问题描述

当我单击项目中的复选按钮时,它没有执行正确的功能。该项目可以在https://github.com/shitwolfymakes/Endless-Sky-Mission-Builder/(indev分支)找到

我正在使用 tkinter 构建一个应用程序,并且正在开发一个函数来动态地将 ttk.Entry 对象放在 ttk.Checkbutton 对象旁边,然后将它们链接在一起。

我已经重写了这个函数几次,甚至添加了一个特殊情况,当 self.numMandatory 为 0 时,但没有任何效果。

这取自 guiutils.py,第 323 行。

# add the optional fields
for i in range(self.numMandatory, self.numFields):
    print(self.rowNum)
    self.listEntryStates.append(BooleanVar())
    self.listEntryData.append(StringVar())
    self.listEntryData[-1].set(self.listDefaultEntryData[i])

    self.listEntries.append(ttk.Entry(self, textvariable=self.listEntryData[-1], state=DISABLED, style="D.TEntry"))
    self.listEntries[-1].grid(row=self.rowNum, column=1, sticky="ew")

    #print(self.listEntryStates[-1])
    #print(self.listEntries)
    self.listCheckbuttons.append(ttk.Checkbutton(self, onvalue=1, offvalue=0, variable=self.listEntryStates[-1],
                                                 command=lambda: self.cbValueChanged(self.listEntryStates[-1],
                                                                                     [self.listEntries[-1]])))
    self.listCheckbuttons[-1].grid(row=self.rowNum, column=2, sticky="e")

    print(self.listCheckbuttons[-1].__str__(), end=" is bound to: ")
    print(self.listEntries[-1].__str__(), self.listEntryStates[-1])

    self.rowNum += 1
# end for

这取自 guiutils.py,第 349 行

def cbValueChanged(self, entryState, modifiedWidgets):

    for widget in modifiedWidgets:
        print("The value of %s is:" % widget, end="\t\t")
        print(entryState.get())
        if type(widget) is str:
            break
        elif entryState.get() is True:
            widget.config(state='enabled', style='TEntry')
        elif entryState.get() is False:
            widget.config(state='disabled', style='D.TEntry')
    #end for

#end cbValueChanged

在主窗口中,当我向下滚动并单击“添加触发器”时,新窗口会正确显示。但是当我单击条目旁边的复选按钮时"[<base#>]",该条目应由 cbValueChanged 启用。

出于某种原因,当添加可选字段的循环运行时, command= 部分仅绑定 self.listEntries 中的最后一个条目(但它绑定每个检查按钮的条目直到最后一次通过循环才创建)

我不确定我还能在哪里问这样的问题,而且我知道这比大多数问题都问得更多。如果您需要更多信息,我很乐意提供。

标签: python-3.xtkinter

解决方案


你~~不能~~编辑:不应该lambda在循环中使用。坦率地说,你根本不应该使用它。使用functools.partial或做一个真正的封闭。

from functools import partial
self.listCheckbuttons.append(ttk.Checkbutton(self, onvalue=1, offvalue=0, variable=self.listEntryStates[-1],
                                             command=partial(self.cbValueChanged,self.listEntryStates[-1],[self.listEntries[-1]])))

推荐阅读