如何在使用 for 循环和字典取消选中 Checkbutton 时禁用 tkinter 上的条目

How to disable an Entry on tkinter when a Checkbutton is unchecked using for loop and dictionary

我正在为我的工作开发一个 Windows 应用程序,我对 Python 的了解非常有限,所以我不知道如何解决这个问题:

我想在取消选中复选框时禁用框架内的每个条目小部件,并在选中复选框时启用框架内的每个条目小部件,并默认选中它们。 我尝试了这段代码,我从 this tutorial 中提取了一部分,但它没有按预期工作。

from tkinter import *

class Principal():
    def __init__(self):
        self.root= Tk()
        self.root.geometry('800x800') 

        self.prixArticlesFrame = LabelFrame(self.root, text="Prix des articles", width=2000)
        self.prixArticlesFrame.place(relx = 0.75, rely = 0.15,anchor = N)

        self.DefautArticlesCheckButton={
            "Deblai" : IntVar(),
            "Remblai" : IntVar(),
            "Blocage" : IntVar(),
            "Beton de propreté": IntVar(),
            "Beton armé": IntVar(),
            "Acier à haute adherence": IntVar(),
            "Joint de dilatation": IntVar(),
            
        }
        for index, (key, value) in enumerate(self.DefautArticlesCheckButton.items()):
            self.cur_check = Checkbutton(self.prixArticlesFrame, 
            text=key,variable=self.DefautArticlesCheckButton[key], onvalue=1, 
            offvalue=0,command=self.ArticlesEntryState) 
            self.cur_check.grid(row=index, column=0, padx=10, pady=10, sticky="W")

        self.DefautArticlesEntries={
            "Deblai" : StringVar(),
            "Remblai" : StringVar(),
            "Blocage" : StringVar(),
            "Beton de propreté": StringVar(),
            "Beton armé": StringVar(),
            "Acier à haute adherence": StringVar(),
            "Joint de dilatation": StringVar(),
            
        }

        for index, (key, value) in enumerate(self.DefautArticlesEntries.items()):
            self.cur_entry = 'DefautArticlesEntries' +key
            
            self.cur_entry=Entry(self.prixArticlesFrame,width=10,
                          textvariable=self.DefautArticlesEntries[key])
            self.cur_entry.grid(row=index,column=2,padx=10)
            self.cur_entry.config(state=NORMAL)
        self.root.mainloop()
    
    def ArticlesEntryState(self):
        for index, (key, value) in enumerate(self.DefautArticlesCheckButton.items()):
            
            if self.DefautArticlesCheckButton[key].get() == 1:
                self.cur_entry.grid(row=index,column=2,padx=10)
                self.cur_entry.config(state=NORMAL)

            elif self.DefautArticlesCheckButton[key].get() == 0:
                self.cur_entry.config(state=DISABLED)

app = Principal()

here is what I got in gif image

我做错了什么? 谢谢

据我了解。您要求 link 检查按钮和行编辑。我给 link.

示例代码
import tkinter
from tkinter import *

def test():
    if e['state'] == 'normal':
        e['state'] = 'disabled'
    else:
        e['state'] = 'normal'

w=Tk()
e=Entry()
e.pack()
cb=Checkbutton(command=test)
cb.select()
cb.pack()
w.mainloop()

更新:

正如@acw1668 所说,当 checkbutton 被选中或未选中时,我使用 self.cur_entry 来更改 entry 的状态,这只会更改最后一个 entry'状态。 我创建了一个列表并将创建的条目附加到它:

from tkinter import *

class Principal():
    
    def __init__(self):
        
        self.root= Tk()

        self.root.geometry('800x800') 
        
        self.AjouterArticleFrame = LabelFrame(self.root, text="Ajouter un article", width=2000)
        self.AjouterArticleFrame.place_forget()

        self.DefautArticlesCheckButton={
            "Deblai" : IntVar(value=1),
            "Remblai" : IntVar(value=1),
            "Blocage" : IntVar(value=1),
            "Beton de propreté": IntVar(value=1),
            "Beton armé": IntVar(value=1),
            "Acier à haute adherence": IntVar(value=1),
            "Joint de dilatation": IntVar(value=1),
            }
        
        self.variablesList=[]
        for index, (key, value) in enumerate(self.DefautArticlesCheckButton.items()):
            checkbutton_=Checkbutton(self.prixArticlesFrame, text=key,variable=self.DefautArticlesCheckButton[key], onvalue=1, offvalue=0,command=self.DefaultArticlesEntryState)
            checkbutton_.grid(row=index, column=0, padx=10, pady=10, sticky="W")
            self.variablesList.append(self.DefautArticlesCheckButton[key])

        
        self.DefautArticlesPrix=[
            "Deblai" ,
            "Remblai" ,
            "Blocage" ,
            "Beton de propreté" ,
            "Beton armé" ,
            "Acier à haute adherence" ,
            "Joint de dilatation",
        ]
        self.DefautArticlesPrixEntriesWidgets=[]


        for i in self.DefautArticlesPrix:
            entry_prix=Entry(self.prixArticlesFrame,width=10)
            entry_prix.grid(row=self.DefautArticlesPrix.index(i),column=2,padx=10)
            self.DefautArticlesPrixEntriesWidgets.append(entry_prix)


    def DefaultArticlesEntryState(self):
        for i in range(len(self.variablesList)):
            if int(self.variablesList[i].get()) == 1:
                self.DefautArticlesPrixEntriesWidgets[i].grid(row=i,column=2,padx=10)
                self.DefautArticlesPrixEntriesWidgets[i].config(state=NORMAL)

            elif int(self.variablesList[i].get()) == 0:
                self.DefautArticlesPrixEntriesWidgets[i].config(state=DISABLED) 

app = Principal()
             
        
      

由于您希望默认选中所有按钮,因此所有变量的初始值都应与其 onvalue.

相匹配

此外,两个字典都引用变量而不是实际的小部件,因此每个 Entry 必须绑定到相应的 IntVar 跟踪回调的范围 - 否则,只有最后一个循环项被引用:

        for index, (key, value) in enumerate(self.DefautArticlesCheckButton.items()):
            value.set(1)
            check = Checkbutton(self.prixArticlesFrame, text=key, variable=value)
            check.grid(row=index, column=0, padx=10, pady=10, sticky="W")

        # ...

        for index, (key, value) in enumerate(self.DefautArticlesEntries.items()):
            entry = Entry(self.prixArticlesFrame, width=10, textvariable=value)
            entry.grid(row=index, column=1, padx=10)

            var = self.DefautArticlesCheckButton[key]
            handler = lambda *_, e=entry, v=var: e.config(state=NORMAL if v.get() else DISABLED)
            var.trace('w', handler)