I'm working on a Windows application for my work and my knowledge on Python is very limited, so I didn't know how to figure this out :
I want to make each entry widget inside the frame disabled when its checkbutton is unchecked and enabled when its checkbutton is checked and make them all checked by default. I tried this code that I took part of it from this tutorial but it didn't work as expected.
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
What I have done wrong? Thanks
CodePudding user response:
As per my understanding. you are asking to link check button and Line Edit. i given example code to 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()
CodePudding user response:
As @acw1668 said, I used self.cur_entry
to change the entry
's state when checkbutton
is checked or unchecked and this only change the last entry
's state.
I created instead a list and appended the entries created to it :
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()
CodePudding user response:
Since you want all buttons checked by default, all variables should have an initial value that matches their onvalue
.
Besides, both dicts refer to the variables rather than the actual widgets, so each Entry
must be bound to the scope of the corresponding IntVar
trace callback - otherwise, only the last loop item is referenced:
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)