_tkinter.TclError: can't invoke "update" command: application has been destroyed error
_tkinter.TclError: can't invoke "update" command: application has been destroyed error
我有以下代码,在我在程序末尾添加 while 循环之前工作正常,它基本上寻求保持循环 运行ning 永远(更新屏幕)直到 window 已关闭。
while 1:
tk.update_idletasks()
tk.update()
time.sleep(0.01)
将上述代码添加到现有代码后,程序 运行s,但在退出时...出现此 错误:
_tkinter.TclError: can't invoke "update" command: application has been destroyed error
我在 SO 上看到过类似的问题,但是 none 对于这个特定问题和 none 的答案可能对我的具体情况有所帮助。
完整代码如下:
Question/Problem: 是什么导致了这个错误,我该如何解决?
from tkinter import *
import random
import time
tk=Tk()
tk.title("My 21st Century Pong Game")
tk.resizable(0,0)
tk.wm_attributes("-topmost",1)
canvas=Canvas(tk,bg="white",width=500,height=400,bd=0,highlightthickness=0)
canvas.pack()
tk.update()
class Ball: #create a ball class
def __init__(self,canvas,color): #initiliased with the variables/attributes self, canvas, and color
self.canvas=canvas #set the intiial values for the starting attributes
self.id=canvas.create_oval(30,30,50,50,fill=color) #starting default values for the ball
""" Note: x and y coordinates for top left corner and x and y coordinates for the bottom right corner, and finally the fill colour for the oval
"""
self.canvas.move(self.id,0,0) #this moves the oval to the specified location
def draw(self): #we have created the draw method but it doesn't do anything yet.
pass
ball1=Ball(canvas,'green') #here we are creating an object (green ball) of the class Ball
while 1:
tk.update_idletasks()
tk.update()
time.sleep(0.01)
说明更新:
另外值得说明的是:
主循环是程序的核心部分,IDLE 已经有一个主循环 - 但是如果你 运行 这个程序在 IDLE 之外,canvas 会出现然后消失一瞬间。为了阻止 window 关闭,我们需要一个动画循环 - 因此 while 1: ..... 否则,正如用户在下面评论的那样,我们不需要 while 1: 因为 IDLE 已经有了这个就位(它在 IDLE 中工作正常,无需使用 while 1:..etc)
您实际上是在尝试实现自己的 mainloop
而不是使用它。
要了解mainloop
,可以阅读一下。您可以将其视为您添加的新代码的语法抽象;你的 while
循环。您几乎是在尝试通过自己循环 "update the screen" 来重新创建轮子,而当轮子已经存在时!
退出程序时,使用sys.exit()
.
可以避免错误
编辑:
替换以下代码:
while 1:
tk.update_idletasks()
tk.update()
time.sleep(0.01)
有了这个:
tk.mainloop()
你的错误是因为,正如它所说,如果 window 已被销毁,你将无法更新它。 mainloop
应该处理这个问题。
当您退出您的应用程序时,下次您调用 update_idletasks
时,window 对象将被销毁。然后您尝试在不存在的 window 上调用 update
。
您需要删除所有以 while
开头的四行,并将它们替换为能够正确处理 window.
销毁的单行 tk.mainloop()
此外,如果您想保留原始代码,则没有理由同时调用 update_idletasks
和 update
。前者是后者的子集。
我同意其他人的意见,您应该在此处使用 mainloop()
,但是如果您想保留原始代码,我会这样做,即跟踪布尔值并执行 while x == True
反而。这样我们就可以将 x 的值更新为等于 False
,这应该可以防止错误发生。
我们可以使用 protocol()
方法在应用程序关闭时更新我们的布尔值。
如果我们将此添加到您的代码中:
x = True
def update_x():
global x
x = False
tk.protocol("WM_DELETE_WINDOW", update_x)
并将您的 while 语句更改为:
while x == True:
tk.update_idletasks()
tk.update()
time.sleep(0.01)
因此您的完整代码可能如下所示:
from tkinter import *
import random
import time
tk=Tk()
tk.title("My 21st Century Pong Game")
tk.resizable(0,0)
tk.wm_attributes("-topmost",1)
x = True
def update_x():
global x
x = False
tk.protocol("WM_DELETE_WINDOW", update_x)
canvas=Canvas(tk,bg="white",width=500,height=400,bd=0,highlightthickness=0)
canvas.pack()
tk.update()
class Ball:
def __init__(self,canvas,color):
self.canvas=canvas
self.id=canvas.create_oval(30,30,50,50,fill=color)
""" Note: x and y coordinates for top left corner and x and y coordinates for the bottom right corner, and finally the fill colour for the oval
"""
self.canvas.move(self.id,0,0)
def draw(self):
pass
ball1=Ball(canvas,'green')
while x == True:
tk.update_idletasks()
tk.update()
time.sleep(0.01)
这将解决您的问题。
重申其他人所说的,您真正需要的是此处的 mainloop()
而不是您的 while i:
声明。
mainloop()
方法用于重置 Tk()
实例的循环一旦代码到达显示 tk.mainloop()
的行,它将成为下一个循环你的代码。
编写代码的正确方法是只使用 mainloop()
,因为它会为 tkinter 实例执行所有更新。
使用 mainloop()
查看下面的代码:
from tkinter import *
tk=Tk()
tk.title("My 21st Century Pong Game")
tk.resizable(0,0)
tk.wm_attributes("-topmost",1)
canvas=Canvas(tk,bg="white",width=500,height=400,bd=0,highlightthickness=0)
canvas.pack()
tk.update()
class Ball:
def __init__(self,canvas,color):
self.canvas=canvas
self.id=canvas.create_oval(30,30,50,50,fill=color)
""" Note: x and y coordinates for top left corner and x and y coordinates for the bottom right corner, and finally the fill colour for the oval
"""
self.canvas.move(self.id,0,0)
def draw(self):
pass
ball1=Ball(canvas,'green')
tk.mainloop()
我有以下代码,在我在程序末尾添加 while 循环之前工作正常,它基本上寻求保持循环 运行ning 永远(更新屏幕)直到 window 已关闭。
while 1:
tk.update_idletasks()
tk.update()
time.sleep(0.01)
将上述代码添加到现有代码后,程序 运行s,但在退出时...出现此 错误:
_tkinter.TclError: can't invoke "update" command: application has been destroyed error
我在 SO 上看到过类似的问题,但是 none 对于这个特定问题和 none 的答案可能对我的具体情况有所帮助。
完整代码如下:
Question/Problem: 是什么导致了这个错误,我该如何解决?
from tkinter import *
import random
import time
tk=Tk()
tk.title("My 21st Century Pong Game")
tk.resizable(0,0)
tk.wm_attributes("-topmost",1)
canvas=Canvas(tk,bg="white",width=500,height=400,bd=0,highlightthickness=0)
canvas.pack()
tk.update()
class Ball: #create a ball class
def __init__(self,canvas,color): #initiliased with the variables/attributes self, canvas, and color
self.canvas=canvas #set the intiial values for the starting attributes
self.id=canvas.create_oval(30,30,50,50,fill=color) #starting default values for the ball
""" Note: x and y coordinates for top left corner and x and y coordinates for the bottom right corner, and finally the fill colour for the oval
"""
self.canvas.move(self.id,0,0) #this moves the oval to the specified location
def draw(self): #we have created the draw method but it doesn't do anything yet.
pass
ball1=Ball(canvas,'green') #here we are creating an object (green ball) of the class Ball
while 1:
tk.update_idletasks()
tk.update()
time.sleep(0.01)
说明更新:
另外值得说明的是:
主循环是程序的核心部分,IDLE 已经有一个主循环 - 但是如果你 运行 这个程序在 IDLE 之外,canvas 会出现然后消失一瞬间。为了阻止 window 关闭,我们需要一个动画循环 - 因此 while 1: ..... 否则,正如用户在下面评论的那样,我们不需要 while 1: 因为 IDLE 已经有了这个就位(它在 IDLE 中工作正常,无需使用 while 1:..etc)
您实际上是在尝试实现自己的 mainloop
而不是使用它。
要了解mainloop
,可以阅读一下while
循环。您几乎是在尝试通过自己循环 "update the screen" 来重新创建轮子,而当轮子已经存在时!
退出程序时,使用sys.exit()
.
编辑:
替换以下代码:
while 1:
tk.update_idletasks()
tk.update()
time.sleep(0.01)
有了这个:
tk.mainloop()
你的错误是因为,正如它所说,如果 window 已被销毁,你将无法更新它。 mainloop
应该处理这个问题。
当您退出您的应用程序时,下次您调用 update_idletasks
时,window 对象将被销毁。然后您尝试在不存在的 window 上调用 update
。
您需要删除所有以 while
开头的四行,并将它们替换为能够正确处理 window.
tk.mainloop()
此外,如果您想保留原始代码,则没有理由同时调用 update_idletasks
和 update
。前者是后者的子集。
我同意其他人的意见,您应该在此处使用 mainloop()
,但是如果您想保留原始代码,我会这样做,即跟踪布尔值并执行 while x == True
反而。这样我们就可以将 x 的值更新为等于 False
,这应该可以防止错误发生。
我们可以使用 protocol()
方法在应用程序关闭时更新我们的布尔值。
如果我们将此添加到您的代码中:
x = True
def update_x():
global x
x = False
tk.protocol("WM_DELETE_WINDOW", update_x)
并将您的 while 语句更改为:
while x == True:
tk.update_idletasks()
tk.update()
time.sleep(0.01)
因此您的完整代码可能如下所示:
from tkinter import *
import random
import time
tk=Tk()
tk.title("My 21st Century Pong Game")
tk.resizable(0,0)
tk.wm_attributes("-topmost",1)
x = True
def update_x():
global x
x = False
tk.protocol("WM_DELETE_WINDOW", update_x)
canvas=Canvas(tk,bg="white",width=500,height=400,bd=0,highlightthickness=0)
canvas.pack()
tk.update()
class Ball:
def __init__(self,canvas,color):
self.canvas=canvas
self.id=canvas.create_oval(30,30,50,50,fill=color)
""" Note: x and y coordinates for top left corner and x and y coordinates for the bottom right corner, and finally the fill colour for the oval
"""
self.canvas.move(self.id,0,0)
def draw(self):
pass
ball1=Ball(canvas,'green')
while x == True:
tk.update_idletasks()
tk.update()
time.sleep(0.01)
这将解决您的问题。
重申其他人所说的,您真正需要的是此处的 mainloop()
而不是您的 while i:
声明。
mainloop()
方法用于重置 Tk()
实例的循环一旦代码到达显示 tk.mainloop()
的行,它将成为下一个循环你的代码。
编写代码的正确方法是只使用 mainloop()
,因为它会为 tkinter 实例执行所有更新。
使用 mainloop()
查看下面的代码:
from tkinter import *
tk=Tk()
tk.title("My 21st Century Pong Game")
tk.resizable(0,0)
tk.wm_attributes("-topmost",1)
canvas=Canvas(tk,bg="white",width=500,height=400,bd=0,highlightthickness=0)
canvas.pack()
tk.update()
class Ball:
def __init__(self,canvas,color):
self.canvas=canvas
self.id=canvas.create_oval(30,30,50,50,fill=color)
""" Note: x and y coordinates for top left corner and x and y coordinates for the bottom right corner, and finally the fill colour for the oval
"""
self.canvas.move(self.id,0,0)
def draw(self):
pass
ball1=Ball(canvas,'green')
tk.mainloop()