Tkinter optionmenu 不允许我根据所做的选择传递要更新的对象的框架

Tkinter optionmenu won't allow me to pass the frame of the object I want to update depending on the choice made

我有一个框架列表,每个框架都有一个带有相同选项列表的选项菜单。当在该特定选项菜单中做出选择时,我只能更改最后一个条目小部件,而不是相应的小部件。在其他小部件中,我已经能够使用类似 "lambda F=F:function(args)" 的东西,但它在这里不起作用。

我试过跟踪选项菜单中的变量,我试过包装函数,我试过选项菜单小部件命令部分中 lambda 的所有组合。大多数方法都会产生错误,有些方法(如所附的方法)会修改底部 frame/entry 而不是正确的对应方法。

这似乎不应该太难。如果选择的顶部框架的选项是 "Continuous" 或 "Discrete",它旁边的条目应该是 'normal' 状态,带有“?..?”在框中,如果它是分类的,它应该更改为 'disabled' 没有内容。如果我能以某种方式将 Frame 字典键传递给 "updateOnChange" 函数,我可以很容易地做到这一点,但我不能,它只允许传递一个参数,那就是 mType[F] 的字符串值。

from tkinter import *

def updateOnChange(type):
    print(type)
    if type.upper()=='CATEGORICAL':
        rangeEntry[F].delete(0,END)
        rangeEntry[F].config(state='disabled')
        print("runCat")
    else:
        rangeEntry[F].config(state='normal')
        rangeEntry[F].delete(0,END)
        rangeEntry[F].insert(0,'?..?')
        print("runCont")

mType={}
frame={}
om={}
rangeEntry={}
root=Tk()
Frames=['FrameOne','FrameTwo']
miningTypes=['Continuous','Categorical','Discrete']
for F in Frames:
    mType[F]=StringVar(root)
    if F=='FrameOne':
        mType[F].set("Continuous")
    else:
        mType[F].set("Categorical")
    frame[F]=Frame(root,borderwidth=3,relief=SUNKEN)
    frame[F].pack(side=TOP,fill=X)
    rangeEntry[F]=Entry(frame[F],width=20,font=("Arial",12))
    om[F]=OptionMenu(frame[F],mType[F],*miningTypes,command=updateOnChange)
    om[F].pack(side=LEFT)
    rangeEntry[F].pack(side=LEFT)
mainloop()


``

您的 updateOnChange 函数将要更改的条目硬编码为 rangeEntry[F],它指向在您的 for 循环中创建的最后一个 Entry 小部件。要正确关联每个条目,您应该将小部件作为参数传递:

def updateOnChange(type, entry):
    if type.upper()=='CATEGORICAL':
        entry.delete(0,END)
        entry.config(state='disabled')
        print("runCat")
    else:
        entry.config(state='normal')
        entry.delete(0,END)
        entry.insert(0,'?..?')
        print("runCont")

然后在你的command中传递参数:

om[F]= OptionMenu(frame[F],mType[F],*miningTypes,command=lambda e, i=rangeEntry[F]: updateOnChange(e, i))