Is there a way to gray out (disable) a tkinter Frame?

Big Sharpie picture Big Sharpie · Jul 24, 2014 · Viewed 16.9k times · Source

I want to create a GUI in tkinter with two Frames, and have the bottom Frame grayed out until some event happens.

Below is some example code:

from tkinter import *
from tkinter import ttk

def enable():
    frame2.state(statespec='enabled') #Causes error

root = Tk()

#Creates top frame
frame1 = ttk.LabelFrame(root, padding=(10,10,10,10))
frame1.grid(column=0, row=0, padx=10, pady=10)

button2 = ttk.Button(frame1, text="This enables bottom frame", command=enable)
button2.pack()

#Creates bottom frame
frame2 = ttk.LabelFrame(root, padding=(10,10,10,10))
frame2.grid(column=0, row=1, padx=10, pady=10)
frame2.state(statespec='disabled') #Causes error

entry = ttk.Entry(frame2)
entry.pack()

button2 = ttk.Button(frame2, text="button")
button2.pack()

root.mainloop()

Is this possible without having to individually gray out all of the frame2's widgets?

I'm using Tkinter 8.5 and Python 3.3.

Answer

Big Sharpie picture Big Sharpie · Jul 24, 2014

Not sure how elegant it is, but I found a solution by adding

for child in frame2.winfo_children():
    child.configure(state='disable')

which loops through and disables each of frame2's children, and by changing enable() to essentially reverse this with

def enable(childList):
    for child in childList:
        child.configure(state='enable')

Furthermore, I removed frame2.state(statespec='disabled') as this doesn't do what I need and throws an error besides.

Here's the complete code:

from tkinter import *
from tkinter import ttk

def enable(childList):
    for child in childList:
        child.configure(state='enable')

root = Tk()

#Creates top frame
frame1 = ttk.LabelFrame(root, padding=(10,10,10,10))
frame1.grid(column=0, row=0, padx=10, pady=10)

button2 = ttk.Button(frame1, text="This enables bottom frame", 
                     command=lambda: enable(frame2.winfo_children()))
button2.pack()

#Creates bottom frame
frame2 = ttk.LabelFrame(root, padding=(10,10,10,10))
frame2.grid(column=0, row=1, padx=10, pady=10)

entry = ttk.Entry(frame2)
entry.pack()

button2 = ttk.Button(frame2, text="button")
button2.pack()

for child in frame2.winfo_children():
    child.configure(state='disable')

root.mainloop()