2016-07-26 85 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()