I am having some issues with the trace method. I am trying to build a form which can change depending on the first option.
MCVE:
from tkinter import *
from tkcalendar import Calendar, DateEntry
root = Tk()
def new_client_window_2(event=None, w=None, fn=None, on=None, sn=None, dob=None, ge=None, ctype=None, *args):
print(type(w))
children = w.winfo_children()
for child in children:
child.pack_forget()
child.destroy()
typeF = Frame(w, padx=10)
typeF.pack(fill=X, expand=1)
Label(typeF, text="Gender:", bg="white", width=10).pack(side=LEFT, fill=X, expand=1)
tyOPTIONS = [None, "School", "Private", "NHS", "YOT", "Other"]
typeE = StringVar(typeF)
print(ctype)
if ctype != "None":
typeE.set(tyOPTIONS[tyOPTIONS.index(ctype)])
else:
typeE.set(tyOPTIONS[0])
typeD = OptionMenu(*(typeF, typeE) + tuple(tyOPTIONS))#, command=lambda e=Event(), w=window, f=fn, o=on, s=sn, d=dob, g=ge, t=typeE.get(): self.new_client_window_2(e, w, f, o, s, d, g, ctype=t))
typeD.pack(side=LEFT, fill=X, expand=1)
typeE.trace("w", lambda e=Event(), w=w, f=fn, o=on, s=sn, d=dob, g=ge, t=typeE.get(): new_client_window_2(event=e, w=w, fn=f, on=o, sn=s, dob=d, ge=g, ctype=t))
def new_client_window(event):
window = Frame(root, padx=5, pady=5)
window.pack(fill=BOTH, expand=1)
fnameF = Frame(window, padx=10)
fnameF.pack(fill=X, expand=1)
onameF = Frame(window, padx=10)
onameF.pack(fill=X, expand=1)
snameF = Frame(window, padx=10)
snameF.pack(fill=X, expand=1)
dobF = Frame(window, padx=10)
dobF.pack(fill=X, expand=1)
genderF = Frame(window, padx=10)
genderF.pack(fill=X, expand=1)
Label(fnameF, text="First Name:", bg="white", width=10).pack(side=LEFT, fill=X, expand=1)
fname = Entry(fnameF)
fname.pack(side=LEFT, fill=X, expand=1)
Label(onameF, text="Other Name(s):", bg="white", width=10).pack(side=LEFT, fill=X, expand=1)
oname = Entry(onameF)
oname.pack(side=LEFT, fill=X, expand=1)
Label(snameF, text="Surname:", bg="white", width=10).pack(side=LEFT, fill=X, expand=1)
sname = Entry(snameF)
sname.pack(side=LEFT, fill=X, expand=1)
Label(dobF, text="DOB:", bg="white", width=10).pack(side=LEFT, fill=X, expand=1)
cal = DateEntry(dobF, width=12, background='darkblue', foreground='white', borderwidth=2)
cal.pack(side=LEFT, fill=X, expand=1)
Label(genderF, text="Gender:", bg="white", width=10).pack(side=LEFT, fill=X, expand=1)
geOPTIONS = [None, "Male", "Female", "Other"]
genderE = StringVar(genderF)
genderE.set(geOPTIONS[0])
genderD = OptionMenu(*(genderF, genderE) + tuple(geOPTIONS))
genderD.pack(side=LEFT, fill=X, expand=1)
Button(window, text="Next", command=lambda e=Event(), w=window, f=fname, o=oname, s=sname, d=cal, g=genderE: new_client_window_2(event=e, w=w, fn=f, on=o, sn=s, dob=d, ge=g, ctype=None)).pack()
new_client_window(Event())
root.mainloop()
as you can see i need to pass some variables into this function from the previous section of the form (static form), then when "ctpyeE" is changed to one of the options i need to re-run the same function but this time know what ctpyeE is set as. I can then use that to adjust the rest of the form.
The error i am getting is from w.winfo_children(), w is the frame i am using to hold the form, however once ctypeE changes and the trace runs it changes its self to an empty string.
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files (x86)\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "C:\Users\Scott\Desktop\patient\caseload.py", line 892, in <lambda>
typeE.trace("w", lambda e=Event(), w=w, f=fn, o=on, s=sn, d=dob, g=ge, t=typeE.get(): self.new_client_window_2(event=e, w=w, fn=f, on=o, sn=s, dob=d, ge=g, ctype=t))
File "C:\Users\Scott\Desktop\patient\caseload.py", line 877, in new_client_window_2
children = w.winfo_children()
AttributeError: 'str' object has no attribute 'winfo_children'
I am assuming the Trace function is setting its own variables in the function but i can't find any documentation on what these variables are so i can account for them.
Notes:
self.tku is my own class, cFrame and cButton are just Frame/Button with pack() added to make it a single line, it should be easy to adjust for those.
fn, on, sn, dob and ge are all Entry Widget objects. and w is the Frame that holds the form.