Brian Tiong
Brian Tiong

Reputation: 21

Python Tkinter TclError

I designed an arc which can rotate, but I can't figure out why IDLE tells me there is still an error in my code.

Here is my code:

from Tkinter import*
from math import *
from time import sleep
pai=Tk()
cv=Canvas(pai,width=1100,height=631,bg="white")
cv.pack()
bb=(150,110,550,510)
temp1=0
temp2=24
t=0
arc1=cv.create_arc(bb,start=temp1,extent=temp2,fill="yellow")
while True:
    t=0.51
    temp1+=t
    cv.itemconfig(arc1,start=temp1)
    cv.update()

And this is the results:

Traceback (most recent call last):
  File "C:\Users\amazi\Desktop\作业\s.py", line 15, in <module>
    cv.itemconfig(arc1,start=temp1)
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 2408, in itemconfigure
    return self._configure(('itemconfigure', tagOrId), cnf, kw)
  File "C:\Python27\lib\lib-tk\Tkinter.py", line 1321, in _configure
    self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
TclError: invalid command name ".93591304L"

Upvotes: 1

Views: 12226

Answers (2)

Nae
Nae

Reputation: 15315

I believe you're getting that error because you're trying to access widgets while there's none, similar to this question. When you close the application with x button, while True loop tries to run at least once more on widgets that doesn't exist, thus produces an error. If you close the application by closing the command prompt, no error is produced as, where should it appear? Try the below example that animates exactly the way you'd want but without a while True loop, which is not easily used along tkinter anyway:

import tkinter as tk
root = tk.Tk()
cv = tk.Canvas(root, width=1100, height=631, bg='white')
cv.pack()
bb = (150,110,550,510)
temp1 = 0
temp2 = 24
arc1=cv.create_arc(bb, start=temp1, extent=temp2, fill='yellow')

def rotate():
    global temp1
    t = 0.51
    temp1 = (temp1 + t) % 360
    print(temp1)
    cv.itemconfig(arc1,start=temp1)
    cv.update_idletasks()
    cv.after(0, rotate)

cv.after(0, rotate)
root.mainloop()

Using Bryan's suggestion below another example may be produced. You may need to tweak t in below example though:

import tkinter as tk
root = tk.Tk()
cv = tk.Canvas(root, width=1100, height=631, bg='white')
cv.pack()
bb = (150,110,550,510)
temp1 = 0
temp2 = 24
arc1=cv.create_arc(bb, start=temp1, extent=temp2, fill='yellow')

def rotate():
    global temp1
    t = 1
    temp1 = (temp1 + t) % 360
    print(temp1)
    cv.itemconfig(arc1,start=temp1)
    cv.after(1, rotate)

rotate()
root.mainloop()

Upvotes: 2

zlmonroe
zlmonroe

Reputation: 360

It seems to me that your code runs fine while it's running -- it's just ending it that is the problem. Did it give that error when you closed the application?

I modified the while True: block to for i in range(500): to verify this and as long as your loop doesn't expect to continue it closes perfectly.

Here are two possible ways you could fix this:

The easy way, catch the error:

from Tkinter import*

pai=Tk()
cv=Canvas(pai,width=1100,height=631,bg="white")
cv.pack()
bb=(150,110,550,510)
temp1=0
temp2=24
t=0
arc1=cv.create_arc(bb,start=temp1,extent=temp2,fill="yellow")
while True:
    t=0.51
    temp1+=t
    try:
        cv.itemconfig(arc1,start=temp1)
        cv.update()
    except TclError:
        pass
pai.mainloop()

The hard way, don't make the error happen (give the gui a second to catch up):

import Tkinter as tk

def on_closing():
    pai.cont = False

pai = tk.Tk()
pai.protocol("WM_DELETE_WINDOW", on_closing)
cv = tk.Canvas(pai,width=1100,height=631,bg="white")
cv.pack()
bb = (150,110,550,510)
temp1 = 0
temp2 = 24
t = 0
arc1 = cv.create_arc(bb,start=temp1,extent=temp2,fill="yellow")

pai.cont = True
while pai.cont:
    t=0.51
    temp1+=t
    cv.itemconfig(arc1,start=temp1)
    cv.update()

pai.destroy()

Personally though, while I don't usually suggest catching errors, I wouldn't go with the second option. Essentially what I'm doing there is creating a variable that tells the while loop whether it should continue or not, then when you click the close button updating that while to end. The infinite while loop is the main problem here in my opinion. Once it ends and the GUI can finish, it all works out.

Upvotes: 0

Related Questions