Getting Bad State Value error trying to toggle variables

31 Views Asked by At

I'm stuck on this code. I'm getting a Bad State Value (_tkinter.TclError: bad state value "SkyBlue1": must be normal, hidden, or disabled) but I am not sure what is wrong. Can anyone advise?

from tkinter import HIDDEN, NORMAL, Tk, Canvas

def toggle_eyes():
    current_color = c.itemcget(eye_left, 'fill') #check eye - white is open, blue is closed
    new_color = c.body_color if current_color == 'white' else 'white' #sets eye to opposite value
    current_state = c.itemcget(pupil_left, 'state')
    new_state = NORMAL if current_state == HIDDEN else HIDDEN
    print(new_state)
    c.itemconfigure(pupil_left, state=new_state)
    c.itemconfigure(pupil_right, state=new_state)
    c.itemconfigure(eye_left, state=new_color)
    c.itemconfigure(eye_right, state=new_color)

def blink():
    toggle_eyes() #close the eyes
    root.after(250, toggle_eyes) #wait 250 milliseconds and open the eyes
    root.after(3000, blink) #wait 3000 milliseconds, then blink again
    
root = Tk()
c = Canvas(root, width=400, height=400)
#sets the canvas size

c.configure(bg='dark blue', highlightthickness=0)
#sets the background color

c.body_color = 'SkyBlue1'
body = c.create_oval(35, 20, 365, 350, outline=c.body_color, fill=c.body_color)
ear_left = c.create_polygon(75, 80, 75, 10, 165, 70, outline=c.body_color, fill=c.body_color)
ear_right = c.create_polygon(255, 45, 325, 10, 320, 70, outline=c.body_color, fill=c.body_color)
foot_left = c.create_oval(65, 320, 145, 360, outline=c.body_color, fill=c.body_color)
foot_right = c.create_oval(250, 320, 330, 360, outline=c.body_color, fill=c.body_color)
eye_left = c.create_oval(130, 110, 160, 170, outline='black', fill='white')
pupil_left = c.create_oval(140, 145, 150, 155, outline='black', fill='black')
eye_right = c.create_oval(230, 110, 260, 170, outline='black', fill='white')
pupil_right = c.create_oval(240, 145, 250, 155, outline='black', fill='black')
mouth_normal = c.create_line(170, 250, 200, 272, 230, 250, smooth=1, width=2, state=NORMAL)
#make the pet

c.pack()
#arranges components in the Tkinter window

root.after(1000, blink)
#blink after 1 second of starting the program

root.mainloop()
#starts the function that listens for input events like mouse clicks

I tried setting the variables to normal or hidden first. I also tried using print statements to determine where the problem was happening. It seems to me that current_state is a null value although I can't figure out why. The pet blinks once but seems like the next time the function is called (to blink again) is when the error occurs.

Any advice? Thanks!

2

There are 2 best solutions below

0
acw1668 On

I think you want to set the fill color on the following two lines:

c.itemconfigure(eye_left, state=new_color)
c.itemconfigure(eye_right, state=new_color)

But you used wrong keyword state. fill should be used instead:

c.itemconfigure(eye_left, fill=new_color) # used fill keyword
c.itemconfigure(eye_right, fill=new_color) # used fill keyword
0
Suramuthu R On

In the lines 11 and 12, Change from state to fill. I have removed c.configure in the initial configuration and added the configuration value in the c -widget itself. Removed the declaration c.body_color = 'SkyBlue1' and changed all the c.body_color into 'SkyBlue1'. Works fine.

from tkinter import HIDDEN, NORMAL, Tk, Canvas

def toggle_eyes():
    current_color = c.itemcget(eye_left, 'fill') #check eye - white is open, blue is closed
    new_color = 'SkyBlue1' if current_color == 'white' else 'white' #sets eye to opposite value
    current_state = c.itemcget(pupil_left, 'state')
    new_state = NORMAL if current_state == HIDDEN else HIDDEN
    print(new_state)
    c.itemconfigure(pupil_left, state=new_state)
    c.itemconfigure(pupil_right, state=new_state)
    c.itemconfigure(eye_left, fill=new_color)
    c.itemconfigure(eye_right, fill=new_color)

def blink():
    toggle_eyes() #close the eyes
    root.after(250, toggle_eyes) #wait 250 milliseconds and open the eyes
    root.after(3000, blink) #wait 3000 milliseconds, then blink again
    
root = Tk()
c = Canvas(root, width=400, height=400, bg='dark blue', highlightthickness=0)
#sets the canvas size




body = c.create_oval(35, 20, 365, 350, outline='SkyBlue1', fill='SkyBlue1')
ear_left = c.create_polygon(75, 80, 75, 10, 165, 70, outline='SkyBlue1', fill='SkyBlue1')
ear_right = c.create_polygon(255, 45, 325, 10, 320, 70, outline='SkyBlue1', fill='SkyBlue1')
foot_left = c.create_oval(65, 320, 145, 360, outline='SkyBlue1', fill='SkyBlue1')
foot_right = c.create_oval(250, 320, 330, 360, outline='SkyBlue1', fill='SkyBlue1')
eye_left = c.create_oval(130, 110, 160, 170, outline='black', fill='white')
pupil_left = c.create_oval(140, 145, 150, 155, outline='black', fill='black')
eye_right = c.create_oval(230, 110, 260, 170, outline='black', fill='white')
pupil_right = c.create_oval(240, 145, 250, 155, outline='black', fill='black')
mouth_normal = c.create_line(170, 250, 200, 272, 230, 250, smooth=1, width=2, state=NORMAL)
#make the pet

c.pack()
#arranges components in the Tkinter window

root.after(1000, blink)
#blink after 1 second of starting the program

root.mainloop()
#starts the function that listens for input events like mouse clicks