Я создаю программу с графическим интерфейсом python Tkinter, содержащую кнопки, которые будут включены/отключены в зависимости от различных ситуаций. По этой причине я хочу обращаться к кнопкам динамически, а не использовать статические имена. Я создал глобальный словарь, который связывает строковые дескрипторы кнопок с логическим значением, указывающим их желаемое состояние (заполняется во время создания виджета, а значения dict изменяются по мере необходимости в программе), и еще один словарь внутри функции, связывающий те же строковые дескрипторы с имена объектов кнопок.
Поскольку я хочу динамически изменять состояния кнопок, имена объектов не жестко закодированы, вместо этого я пытаюсь использовать getattr с вызовом функции, возвращающим имя объекта с использованием функции словаря, описанной выше:
class WApplication(Frame):
buttonStates={}
...
def buttonDisable(self):
for i in self.buttonStates:
#self.Load_Manifest.config(state=DISABLED) #This line works (i.e., visibly disables the 'Load Manifest' button)
#print(i+".config(state=DISABLED)") #Output: Load_Manifest.config(state=DISABLED)
getattr(self.ObjectDictionary(i),"config(state=DISABLED)") #AttributeError: Button instance has no attribute 'config(state=DISABLED)'
def buttonEnable(self): #Similar error encountered as above when debugging this function
for i in self.buttonStates:
if self.buttonStates[i]==True:
getattr(self.ObjectDictionary(i),"config(state=NORMAL)")
...
def ObjectDictionary(self,string):
"Function that maps dictionary widget keys to their object titles and returns the mapped object title"
switcher={
"Load_Manifest":self.Load_Manifest,
"Update_Manifest":self.Update_Manifest,
"Fresh_Manifest":self.Fresh_Manifest,
"Manifest_Details":self.Manifest_Details
}
return switcher.get(string)
...
def createWidgets(self):
self.QUIT = Button(self.master)
self.QUIT["text"] = "QUIT"
self.QUIT["fg"] = "red"
self.QUIT["command"] = self.quit
self.QUIT.place(x=710,y=10,height=50,width=100)
self.Load_Manifest=Button(self.master)
self.Load_Manifest["text"]="Load Manifest"
self.Load_Manifest["command"]=self.LoadManifestButton
self.Load_Manifest.config(state=NORMAL)
self.Load_Manifest.place(x=10,y=10,height=50,width=110)
self.buttonStates["Load_Manifest"]=True
self.buttonActions["Load_Manifest"]=False
self.Update_Manifest=Button(self.master)
self.Update_Manifest["text"]="Update Manifest"
self.Update_Manifest["command"]=self.UpdateManifestButton
self.Update_Manifest.config(state=DISABLED)
self.Update_Manifest.place(x=130,y=10,height=50,width=120)
self.buttonStates["Update_Manifest"]=False
self.buttonActions["Update_Manifest"]=False
self.Fresh_Manifest=Button(self.master)
self.Fresh_Manifest["text"]="Create New Manifest"
self.Fresh_Manifest["command"]=self.FreshManifestWindowButton
self.Fresh_Manifest.config(state=NORMAL)
self.Fresh_Manifest.place(x=260,y=10,height=50,width=150)
self.buttonStates["Fresh_Manifest"]=True
self.buttonActions["Fresh_Manifest"]=False
...
self.Manifest_Details=Button(self.master)
self.Manifest_Details["text"]="Details"
self.Manifest_Details["command"]=self.ManifestDetailsButton
self.Manifest_Details.config(state=DISABLED)
self.Manifest_Details.place(x=10,y=790,height=50,width=100)
self.buttonStates["Manifest_Details"]=False
self.buttonActions["Manifest_Details"]=False
...
Функции buttonDisable и buttonEnable вызываются в другом месте программы в других функциях, которые запускаются при нажатии кнопки. Я мог бы просто придерживаться жестко закодированных имен виджетов и поместить множество операторов if в мою функцию buttonEnable, поскольку в настоящее время может быть только четыре кнопки, но я планирую расширить программу, добавив дополнительные кнопки, и я хочу отключить все кнопки во время чтобы избежать входа пользователя, когда программа занята, поэтому желательны динамические вызовы.
При первом вызове getattr(self.ObjectDictionary(i),config(state=DISABLED)) возникает ошибка:
AttributeError: Button instance has no attribute 'config(state=DISABLED)'
Но я бы подумал, что .config() является атрибутом объекта виджета? И следующая жестко запрограммированная строка замены self.Load_Manifest.config(state=DISABLED) работает по назначению, что, по моему мнению, должно быть эквивалентно getattr?
config
— это атрибут объекта виджета."config(state=DISALBED)"
не является атрибутом объекта виджета. - person Bryan Oakley   schedule 06.10.2020