Search code examples
pythontkinterstatetkinter-entry

How do I change the entry widget state from disabled to not disabled by using a check box widget?


I am using tkinter 8.6 with python 3.5.2 and I trying to create a GUI so that when I click a check box it allows a user to write something into an entry box. However I am getting an error. Below is my code.

from tkinter import *
from tkinter import ttk

def quit():
    mainframe.quit()

#Write in Function
def write():
    write_in.state(['!disabled']) #Getting Error Here

root = Tk()
root.title("Voting Booth")

#Global variables
var = StringVar()

#Create main widget
mainframe = ttk.Frame(root, padding="3 3 12 12")
mainframe.grid(column=0, row=0, sticky=(N, W, E, S)) 
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)

#Additional widgets
ttk.Label(mainframe, textvariable=var, font=('bold')).grid(column=2, row=0)
vote = ttk.Button(mainframe, text="Vote", command = quit).grid(column=4, row=5, sticky=E)
don_box = ttk.Checkbutton(mainframe, text="Donald Trump").grid(column=2, row=1, sticky=W)
stein_box = ttk.Checkbutton(mainframe, text="Jill Stein").grid(column=2, row=3, sticky=W)
write_box = ttk.Checkbutton(mainframe, text="Write in:", command = write).grid(column=2, row=4, sticky=W)
write_in = ttk.Entry(mainframe, width = 20, state=DISABLED).grid(column=3, row=4, sticky=W)

#Setting variables and widgets
var.set("Presidential Nominees")

for child in mainframe.winfo_children(): child.grid_configure(padx=5, pady=5)

root.mainloop();

However I am getting the following error when I click the write_in checkbox:

" File "/usr/lib/python3.5/tkinter/__init__.py", line 1553, in __call__
return self.func(*args)
File "./booth_gui.py", line 13, in write
write_in.state(['!disabled'])
AttributeError: 'NoneType' object has no attribute 'state' "

Solution

  • You get a NoneType exception because the write_in object is actually None.

    The problem is that you declare write_in as:

    write_in = ttk.Entry(...).grid(column=3, row=4, sticky=W)
    

    But the grid method returns a None result.

    The call to grid must be separated from the widget declaration:

    write_in = ttk.Entry(...)
    write_in.grid(column=3, row=4, sticky=W)
    

    About the way you change the widget's state, I'm not really sure it is supposed to work.

    Try with the config (or configure) widget method and set the state keyword to NORMAL:

    write_in.config(state=NORMAL)