我正在尝试创建一个转轮的动画,并希望在while循环中有一个小延迟,然后每次更新轮。我已经尝试了tkinter中的“after”函数以及python中的“sleep”函数,但它崩溃或完成了conputation并且只显示了最后一个没有实际动画的位置,因为滚轮正在转动。
我为转轮创建的功能:
def turning():
#initial wheel position
global position
pos(position)
#infinite loop turning the wheel
while(1):
root.after(1000, spin)
def spin():
global position
global speed
delspike() #delete current wheel
position += speed #calculate next position
if position > 360:
position -= 360
pos(position) #draw new wheel
为什么这不起作用?
答案 0 :(得分:0)
此代码:
while (1):
root.after(1000, spin)
..将安排spin
函数在1秒内运行。它会在眨眼之间成千上万次。即使你要求spin
在一秒钟内运行,while循环本身也会尽可能快地运行并且永远不会停止。它将在第一次旋转之前安排数十万个旋转,然后它们将一个接一个地运行,因为它们都将尝试在一秒钟内运行。
执行动画的正确方法是让函数在一秒钟内再次安排自己:
def spin():
...
root.after(1000, spin)
然后,您在程序开始时只调用spin
一次,并且无限期地运行。
答案 1 :(得分:0)
after
在您尝试放入循环的函数中使用:
def f():
...
root.after(1000, f)
(1000表示1000毫秒,即1秒。这意味着程序将每1秒执行一次操作。您可以将其更改为您希望的任何数字。)
另外,请注意,在Tkinter中使用无限while
循环(while True
,while 1
等)会使窗口无响应。我们在这里讨论了很多。如果您对SO进行了研究,可以找到这个。
答案 2 :(得分:0)
我注意到许多初学者'不知道更好'尝试使用while循环动画tkinter。事实证明,这不是一个愚蠢的想法。我最近想出了如何使用asyncio和3.5 async-await语法中的新功能来完成这项工作。我还为一个简单的应用程序制定了通用模板。我碰巧喜欢这种风格,而不是使用后循环。如果您安装了3.5.2或3.6.0a3(或安装了),则可以运行此代码并将您的旋转器替换为您的旋转器。
import asyncio
import tkinter as tk
class App(tk.Tk):
def __init__(self, loop, interval=1/120):
super().__init__()
self.loop = loop
self.protocol("WM_DELETE_WINDOW", self.close)
self.tasks = []
self.tasks.append(loop.create_task(
self.rotator(1/60, 1)))
self.updater(interval)
async def rotator(self, interval, d_per_int):
canvas = tk.Canvas(self, height=600, width=600)
canvas.pack()
deg = 0
arc = canvas.create_arc(100, 100, 500, 500,
start=0, extent=deg, fill='blue')
while True:
await asyncio.sleep(interval)
deg = (deg + d_per_int) % 360
canvas.itemconfigure(arc, extent=deg)
def updater(self, interval):
self.update()
self.loop.call_later(interval, self.updater, interval)
def close(self):
for task in self.tasks:
task.cancel()
self.loop.stop()
self.destroy()
loop = asyncio.get_event_loop()
app = App(loop)
loop.run_forever()
loop.close()