Python Tkinter Animation
Your animation
method has a while True
loop in it which never breaks. This is a no-no in a GUI program, because by never returning, it prevents the GUI's event-loop from processing events. So, for example, if you had a Menu, then the user would not be able to select any menu item. The GUI would appear frozen, except for whatever actions you implement in the animation
method.
Here is a slight modification of @Tim's code which fixes this problem by removing the while
loop and simply moving the aliens one step before returning. self.master.after
is called at the end of the animation
method to have the event loop call animation again after a short pause.
import tkinter as tkimport timeclass Alien(object): def __init__(self, canvas, *args, **kwargs): self.canvas = canvas self.id = canvas.create_oval(*args, **kwargs) self.vx = 5 self.vy = 0 def move(self): x1, y1, x2, y2 = self.canvas.bbox(self.id) if x2 > 400: self.vx = -5 if x1 < 0: self.vx = 5 self.canvas.move(self.id, self.vx, self.vy)class App(object): def __init__(self, master, **kwargs): self.master = master self.canvas = tk.Canvas(self.master, width=400, height=400) self.canvas.pack() self.aliens = [ Alien(self.canvas, 20, 260, 120, 360, outline='white', fill='blue'), Alien(self.canvas, 2, 2, 40, 40, outline='white', fill='red'), ] self.canvas.pack() self.master.after(0, self.animation) def animation(self): for alien in self.aliens: alien.move() self.master.after(12, self.animation)root = tk.Tk()app = App(root)root.mainloop()
You never called the animation
method. There were a couple of other naming issues.
# Assuming Python 2.x# For Python 3.x support change print -> print(..) and Tkinter to tkinterfrom Tkinter import *import timeclass alien(object): def __init__(self): self.root = Tk() self.canvas = Canvas(self.root, width=400, height = 400) self.canvas.pack() self.alien1 = self.canvas.create_oval(20, 260, 120, 360, outline='white', fill='blue') self.alien2 = self.canvas.create_oval(2, 2, 40, 40, outline='white', fill='red') self.canvas.pack() self.root.after(0, self.animation) self.root.mainloop() def animation(self): track = 0 while True: x = 5 y = 0 if track == 0: for i in range(0,51): time.sleep(0.025) self.canvas.move(self.alien1, x, y) self.canvas.move(self.alien2, x, y) self.canvas.update() track = 1 print "check" else: for i in range(0,51): time.sleep(0.025) self.canvas.move(self.alien1, -x, y) self.canvas.move(self.alien2, -x, y) self.canvas.update() track = 0 print trackalien()
Here's a way of doing it using a loop:
from tkinter import * # version 3.xtk = Tk()frame = Frame(tk)canvas = Canvas(frame) # use canvasframe.pack(fill = BOTH, expand = 1)canvas.pack(fill = BOTH, expand = 1)ball = canvas.create_oval(10, 10, 30, 30, tags = 'ball') # create object to animatedef animation(x_move, y_move): canvas.move(ball, x_move, y_move) # movement canvas.update() canvas.after(20) # milliseconds in wait time, this is 50 fps tk.after_idle(animation, x_move, y_move) # loop variables and animation, these are updatable variablesanimation(2, 2) # run animation
An updatable variable is a variable that stays the same when updated and can be updated again.