我有以下代码正常工作,直到我在程序结束时添加了way loop,y基本上试图使循环永远运行(更新屏幕),直到窗口为窗口关闭。
while 1:
tk.update_idletasks()
tk.update()
time.sleep(0.01)
在将上述代码添加到现有代码中时,程序运行,但是在退出时...提出了此错误:
_tkinter.TclError: can't invoke "update" command: application has been destroyed error
我已经看到了一个类似的问题,但由于这个错误而没有,但是没有一个答案可以帮助我的特定情况。
整个代码如下:
问题/问题:是什么引起此错误,我该如何修复?
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)
说明更新:
也值得解释:
主循环是程序的中心部分,怠速已经具有主循环 - 但是,如果您在空闲之外运行此程序,则画布将出现,然后在一秒钟后消失。为了阻止窗口关闭,我们需要动画循环 - 因此,1:.....它在闲置时可以很好地工作,而无需使用1:.... etc)
我同意其他人应该在此处使用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()
您正在有效地尝试实现自己的mainloop
而不是使用它。
要了解mainloop
,您可以在此处阅读有关它。您可以将其视为您添加的新代码的句法抽象;您的while
循环。当一个已经存在时,您几乎试图通过制作自己的循环来"更新屏幕"来重新创建轮子!
退出程序时,您可以使用sys.exit()
避免错误。
编辑:
替换以下代码:
while 1:
tk.update_idletasks()
tk.update()
time.sleep(0.01)
与此:
tk.mainloop()
您的错误是因为,如它所说,如果窗口已被销毁,则无法更新该窗口。mainloop
应该处理此。
退出应用程序时,下次致电update_idletasks
时,窗口对象被破坏。然后,您尝试在不存在的窗口上调用update
。
您需要删除以while
开头的所有四行,然后用单行tk.mainloop()
替换它们,该行可正确处理窗口的破坏。
另外,如果您很想保留原始代码,则没有理由拨打update_idletasks
和update
。前者是后者的子集。