Python _tkinter.TclError:无效的命令名称“.4302957584”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16059592/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
_tkinter.TclError: invalid command name ".4302957584"
提问by narzero
When closing the python 3 program, I get a strange exception in the console.
关闭 python 3 程序时,我在控制台中收到一个奇怪的异常。
The Python 3 code:
Python 3 代码:
from tkinter import *
from random import randint
# Return a random color string in the form of #RRGGBB
def getRandomColor():
color = "#"
for j in range(6):
color += toHexChar(randint(0, 15)) # Add a random digit
return color
# Convert an integer to a single hex digit in a character
def toHexChar(hexValue):
if 0 <= hexValue <= 9:
return chr(hexValue + ord('0'))
else: # 10 <= hexValue <= 15
return chr(hexValue - 10 + ord('A'))
# Define a Ball class
class Ball:
def __init__(self):
self.x = 0 # Starting center position
self.y = 0
self.dx = 2 # Move right by default
self.dy = 2 # Move down by default
self.radius = 3
self.color = getRandomColor()
class BounceBalls:
def __init__(self):
self.ballList = [] # Create a list for balls
window = Tk()
window.title("Bouncing Balls")
### Create Canvas ###
self.width = 350
self.height = 150
self.canvas = Canvas(window, bg = "white", width = self.width, height = self.height)
self.canvas.pack()
### Create Buttons ###
frame = Frame(window)
frame.pack()
btStop = Button(frame, text = "Stop", command = self.stop)
btStop.pack(side = LEFT)
btResume = Button(frame, text = "Resume", command = self.resume)
btResume.pack(side = LEFT)
btAdd = Button(frame, text = "Add", command = self.add)
btAdd.pack(side = LEFT)
btRemove = Button(frame, text = "Remove", command = self.remove)
btRemove.pack(side = LEFT)
self.sleepTime = 20
self.isStopped = False
self.animate()
window.mainloop()
def stop(self): # Stop animation
self.isStopped = True
def resume(self):
self.isStopped = False
self.animate()
def add(self): # Add a new ball
self.ballList.append(Ball())
def remove(self):
self.ballList.pop()
def animate(self):
while not self.isStopped:
self.canvas.after(self.sleepTime)
self.canvas.update()
self.canvas.delete("ball")
for ball in self.ballList:
self.redisplayBall(ball)
def redisplayBall(self, ball):
if ball.x > self.width or ball.x < 0:
ball.dx = -ball.dx
if ball.y > self.height or ball.y < 0:
ball.dy = -ball.dy
ball.x += ball.dx
ball.y += ball.dy
self.canvas.create_oval(ball.x - ball.radius, ball.y - ball.radius, \
ball.x + ball.radius, ball.y + ball.radius, \
fill = ball.color, tags = "ball")
BounceBalls()
Here's the full Traceback:
这是完整的回溯:
/Library/Frameworks/Python.framework/Versions/3.3/bin/python3 "/Users/narek_a/Dropbox/Python/PycharmProjects/Introduction to Programming/Chapter 10.py"
Traceback (most recent call last):
File "/Users/narek_a/Dropbox/Python/PycharmProjects/Introduction to Programming/Chapter 10.py", line 446, in <module>
BounceBalls()
File "/Users/narek_a/Dropbox/Python/PycharmProjects/Introduction to Programming/Chapter 10.py", line 407, in __init__
self.animate()
File "/Users/narek_a/Dropbox/Python/PycharmProjects/Introduction to Programming/Chapter 10.py", line 428, in animate
self.canvas.delete("ball")
File "/Library/Frameworks/Python.framework/Versions/3.3/lib/python3.3/tkinter/__init__.py", line 2344, in delete
self.tk.call((self._w, 'delete') + args)
_tkinter.TclError: invalid command name ".4302957584"
Process finished with exit code 1
Why are these exceptions caused?
为什么会导致这些异常?
采纳答案by kalgasnik
Main application loop window.mainloopwill never be executed without pressing stopbutton. It is source of your problem. Rewrite animation loop:
window.mainloop如果不按下stop按钮,主应用程序循环将永远不会执行。这是你问题的根源。重写动画循环:
def __init__(self):
...
self.sleepTime = 20
self.isStopped = False
self.window = window
self.window.after(self.sleepTime, self.animate)
window.mainloop()
...
def animate(self):
if not self.isStopped:
self.canvas.update()
self.canvas.delete("ball")
for ball in self.ballList:
self.redisplayBall(ball)
self.window.after(self.sleepTime, self.animate)
回答by Bryan Oakley
When you exit the program, the windows are destroyed. This destruction happens after the event loop notices the application has exited. The way you have your code structured, this happens when you call self.update(). Immediately after that call, and after the widgets have been destroyed, you are calling self.canvas.delete("ball"). Since the widget was destroyed in the previous statement, you get the error.
当您退出程序时,窗口将被销毁。这种破坏发生在事件循环注意到应用程序已经退出之后。根据您构建代码的方式,这在您调用self.update(). 在该调用之后,并且在小部件被销毁之后,您立即调用self.canvas.delete("ball"). 由于小部件在上一条语句中被销毁,因此您会收到错误消息。
The reason the error is so cryptic is that Tkinter is just a wrapper around a tcl/tk interpreter. Tk widgets are named with a dot followed by some characters, and widget names are also tcl commands. When you call the deletemethod of the canvas, Tkinter translates the canvas reference to the internal tk widget name / tcl command. Because the widget has been destroyed, tk doesn't recognize that as a known command and throws an error.
错误如此神秘的原因是 Tkinter 只是 tcl/tk 解释器的包装器。Tk 小部件以点号后跟一些字符命名,小部件名称也是 tcl 命令。当您调用delete画布的方法时,Tkinter 会将画布引用转换为内部 tk 小部件名称 / tcl 命令。由于小部件已被销毁,tk 无法将其识别为已知命令并引发错误。
The solution is going to require you to redo your animation logic. You should not have your own animation loop. Instead, you need to use the Tkinter eventloop (mainloop()) as your animation loop. There are a few examples on this site to show you how (for example: https://stackoverflow.com/a/11505034/7432)
该解决方案将要求您重做动画逻辑。你不应该有自己的动画循环。相反,您需要使用 Tkinter 事件mainloop()循环( ) 作为您的动画循环。本站点上有一些示例向您展示如何操作(例如:https: //stackoverflow.com/a/11505034/7432)

