pythonnumpytkinter

Why does this tkinter image animation not delay properly?


Here's my attempt, modified from another post, to create a minimal loop where I create a numpy array and display it. (For convenience I have a Start button.)

It works fine, with one exception -- it runs at full speed, regardless of what delay I put in as the first argument to self.after (it's 1000 in the example below. Changing this arg has no visible effect.)

What am I missing? (I am running python 3.8.3. Oh, that's apparently a very old version. Damn. I'll go update just in case that's related to the issue.)

from PIL import ImageTk
import numpy as np
import tkinter as tk

class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.canvas = tk.Canvas(self, width = 1200, height=1200)
        self.canvas.pack()
        tk.Button(self, text="Start", command=self.start_animation).pack()

    def start_animation(self):
        self.canvas.delete('all')

        # generate a random test frame
        im = np.random.randint(0, 255, (1024,1024,3), dtype="uint8")
        im1 = Image.fromarray(im, 'RGB')
        im2 = ImageTk.PhotoImage(im1)

        self.canvas.create_image(600, 600, image=im2)
        self.update()
        self.after(1000, self.start_animation())

if __name__ == '__main__':
    App().mainloop()

Solution

  • Some points here

    tk.Button(self, text="Start", command=self.start_animation)
    
    self.im2 = ImageTk.PhotoImage(im1)
    

    Exaample Code

    from PIL import Image, ImageTk
    import numpy as np
    import tkinter as tk
    
    class App(tk.Tk):
        def __init__(self):
            super().__init__()
            self.canvas = tk.Canvas(self, width = 200, height=200)
            self.canvas.pack()
            tk.Button(self, text="Start", command=self.start_animation).pack()
    
        def start_animation(self):
            self.canvas.delete('all')
    
            # generate a random test frame
            im = np.random.randint(0, 255, (200, 200, 3), dtype="uint8")
            im1 = Image.fromarray(im, 'RGB')
            self.im2 = ImageTk.PhotoImage(im1)
    
            self.canvas.create_image(0, 0, image=self.im2, anchor=tk.NW)
            self.update()
            self.after(1000, self.start_animation)
    
    if __name__ == '__main__':
        App().mainloop()
    

    enter image description here