如何在使用 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)
我正在为我的工作开发一个 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)