我正在尝试在窗口上播放一些简单的动画。这是我第一次使用Tkinter,所以我在每个帧上都设置了对root.update()的调用,以确保它在屏幕上显示出来(否则帧速率有些不稳定)。现在,我了解到这是一种非常糟糕的做法,并尝试将其完全删除,或者用对root.update_idletasks()的调用代替。奇怪的是,当我这样做时,窗口变得没有响应,并最终崩溃了。
我尝试将代码降至最低限度(如下所示),但问题仍然存在。
from tkinter import *
from tkinter import ttk
from PIL import ImageTk, Image
class Application():
def __init__(self):
# WINDOW SETUP
self.root = Tk()
self.root.geometry('512x512')
self.root.protocol('WM_DELETE_WINDOW', self.Annihilation)
self.screen = ttk.Label(self.root)
self.screen.place(relx=.5, rely=.5, anchor="c")
# CALL THE ANIMATION FUNCTION
self.state = 'Idle'
self.Animation(self.state, [self.Idle1, self.Idle2], 500)
self.root.mainloop()
# ANIMATION FUNCTION
def Animation(self, State, framelist, frameduration):
for i in range(len(framelist)):
if self.state == State:
frame = framelist[i]()
self.screen.configure(image = frame)
self.root.update() # THIS IS THE LINE I WANT TO REMOVE
self.root.after(frameduration)
else:
return
self.Animation(State, framelist, frameduration)
# LIST OF IMAGES
def Idle1(self):
return ImageTk.PhotoImage(Image.open('Image1.tif').resize((512, 512)))
def Idle2(self):
return ImageTk.PhotoImage(Image.open('Image2.tif').resize((512, 512)))
def Annihilation(self):
self.root.eval('::ttk::CancelRepeat')
self.state = 'Quitting'
self.root.destroy()
Application()
这闻起来是“您的代码中存在一个更大的错误,即您的第一个错误被意外阻止了”,但是我没有主意,而且我还没有能够谷歌搜索这个错误。任何帮助将不胜感激。
答案 0 :(得分:1)
您不应该使用for
循环,这可能会花费一些时间,并且在每帧之间没有时间也没有任何意义。不要在Animation
中运行Animation
,因为它会创建您不需要的递归。使用after(time, Animation)
我使用self.current_frame
来保持显示哪一帧的信息。 Animation
仅显示一帧,更改self.current_frame
中的值,然后使用after()
再次运行它-替换了for
循环。它还取代了递归。
您也可以只加载一次图像并将图像保留在列表中,而不是将函数名称保留在列表中 从tkinter导入* 从tkinter导入ttk 从PIL导入ImageTk,图像
class Application():
def __init__(self):
# WINDOW SETUP
self.root = Tk()
self.root.geometry('512x512')
self.root.protocol('WM_DELETE_WINDOW', self.annihilation)
self.screen = ttk.Label(self.root)
self.screen.place(relx=.5, rely=.5, anchor="c")
# CALL THE ANIMATION FUNCTION
self.state = 'Idle'
self.current_frame = 0
self.animation(self.state, [self.idle1, self.idle2], 500)
self.root.mainloop()
# ANIMATION FUNCTION
def animation(self, State, framelist, frameduration):
if state == self.state:
# change image
self.frame = framelist[self.current_frame]()
self.screen.configure(image=self.frame)
# get next frame (or first frame)
self.current_frame = (self.current_frame+1) % len(framelist)
# run again after 'frameduration' milliseconds
self.root.after(frameduration, self.animation, State, framelist, frameduration)
# LIST OF IMAGES
def idle1(self):
return ImageTk.PhotoImage(Image.open('Image1.tif').resize((512, 512)))
def idle2(self):
return ImageTk.PhotoImage(Image.open('Image2.tif').resize((512, 512)))
def annihilation(self):
self.root.eval('::ttk::CancelRepeat')
self.state = 'Quitting'
self.root.destroy()
Application()
,我将名称更改为小写