2016-07-26 30 views
0

Ich versuche, eine Animation eines sich drehenden Rades zu erstellen und möchte eine kleine Verzögerung in einer while-Schleife haben und dann das Rad jedes Mal aktualisieren. Ich habe sowohl die "after" -Funktion in tkinter als auch die "sleep" -Funktion in Python ausprobiert, aber entweder stürzt sie ab oder beendet die Conquutation und zeigt mir nur die letzte Position ohne die eigentliche Animation, während sich das Rad dreht.While-Schleife funktioniert nicht in Tkinter Animation

Die Funktion, die ich für das sich drehende Rad geschaffen:

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 

warum funktioniert das nicht?

+0

Versuchen Sie 'root.update_idletasks()' aufzurufen, nachdem Sie das Rad gezeichnet oder neu gezeichnet haben. – martineau

+0

@Pythonista: Nein, die 'while True'-Schleife ist nicht die Lösung.Es wird genau das gleiche schlechte Verhalten haben. –

Antwort

0

after wird innerhalb der Funktion versuchen Sie, die in einer Schleife zu setzen.

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

(1000 bedeutet 1000 Millisekunden, die 1 Sekunde Das bedeutet, das Programm wird eine Operation alle 1 Sekunde durchführen und Sie. kann es Sie wünschen sich auch beliebig ändern.), bedenken Sie, dass, unendliche while Schleife (while True, while 1 etc.) in Tkinter wird das Fenster nicht reagiert machen. Wir haben das hier oft besprochen. Sie könnten dies finden, wenn Sie auf SO recherchiert hätten.

0

Dieser Code:

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

.. wird die spin Funktion planen in 1 Sekunde laufen. Und das wird es tausende Male im Handumdrehen tun. Obwohl Sie spin in einer Sekunde ausführen möchten, wird die While-Schleife selbst so schnell wie möglich ausgeführt und niemals gestoppt. Es wird Hunderttausende von Spins vor dem ersten Dreh planen, und dann werden sie alle nacheinander laufen, da sie alle versuchen werden, in einer Sekunde zu laufen.

Der richtige Weg Animation zu tun ist, um die Funktion Zeitplan selbst wieder in einer Sekunde haben:

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

Dann Sie spin genau einmal zu Beginn des Programms aufrufen, und es läuft auf unbestimmte Zeit.

+0

vielen Dank für die Hilfe das funktioniert super – moonboon

0

Ich habe festgestellt, dass viele Anfänger, die es nicht besser wissen 'versuchen, Tkinter mit einer while-Schleife zu animieren. Es stellt sich heraus, dass dies keine alberne Idee ist. Ich habe vor kurzem herausgefunden, wie dies mit asyncio und der neuen in 3.5 async-await-Syntax funktioniert. Ich habe auch eine generische Vorlage für eine einfache App ausgearbeitet. Ich mag diesen Stil mehr als After-Loops. Wenn Sie 3.5.2 oder 3.6.0a3 installiert haben (oder entweder installieren), können Sie diesen Code ausführen und meinen Rotator durch Ihren ersetzen.

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()