2016-07-26 84 views
0

我想创建一个转轮的动画,并希望在while循环中有一个小的延迟,然后每次更新轮子。我已经尝试了tkinter中的“after”函数以及python中的“sleep”函数,但是它会崩溃或完成该计算,并且只会显示轮子转动时没有实际动画的最后一个位置。虽然循环不工作在tkinter动画

我的转轮产生的功能:

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

尝试在绘制或重绘轮子后调用'root.update_idletasks()'。 – martineau

+0

@Pythonista:不,'while True'循环不是解决方案。它具有完全相同的不良行为。 –

回答

0

after使用您正试图把在一个循环里面的功能:

def f(): 
    ... 
    root.after(1000, f) 

(1000指1000毫秒这是1秒这意味着该方案将执行的操作每隔1秒你。可以将其更改为您希望的任意数字。) 另外,请记住,在Tkinter中使用无限循环(while Truewhile 1等)将使窗口不响应。我们在这里讨论了很多。如果您对SO进行了研究,则可以找到此信息。

0

此代码:

while (1): 
    root.after(1000, spin) 

..将要调度spin函数以在1秒内运行。它将在眨眼之间做上千次。即使您要求spin在一秒钟内运行,while循环本身将尽可能快地运行并永不停止。它将在第一次旋转之前安排数十万次旋转,然后它们将一个接一个地旋转,因为它们都将在一秒钟内尝试运行。

做动画正确的方法是在一秒钟内再次有功能的时间表本身:

def spin(): 
    ... 
    root.after(1000, spin) 

然后,你在你的程序开始拨打spin只有一次,而且无限期地运行。

+0

非常感谢这个帮助很好的帮助 – moonboon

0

我注意到许多初学者'不知道更好'尝试使用t whileter循环动画tkinter。事实证明,这不是一个愚蠢的想法。我最近想出了如何使用asyncio和3.5中的新异步等待语法来完成这项工作。我也为一个简单的应用程序制定了一个通用模板。我碰巧喜欢这种风格而不是使用after循环。如果你安装了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()