0

I wrote a small program using tkinter to generate a figure based on parameters I'm giving the program (through gui interface). I am drawing the figure directly with tkinter using Canvas. Now I want to generate a series of figures and put them in animated loop. I can generate a gif animation and load it into the figure but the question is if I can do this directly in tkinter. I can put everything in loop, but then I'll lose the event handler. Any other option?


Edit

Here is a simple script:

#!/usr/bin/python
from Tkinter import *
import ttk
import numpy as np


colors = {1:'#F00',
          2:'#0F0',
          3:'#00F',
          4:'#FF0',
          5:'#0FF'}

root = Tk()
canvas = Canvas(root,width=400,height=400)
label = Label(root,text='seed')
values = StringVar()
combo =  ttk.Combobox(root)


def painter(event):
    seed = int(combo.get())
    np.random.seed(seed)
    nrows =  10
    ncols =  10
    Y = 0
    dx = 400/nrows
    dy = 400/ncols
    for i in range(nrows):
        X = 0
        for j in range(ncols):
            n =  np.random.randint(1,5)
            col =  colors[n]
            canvas.create_rectangle(X,Y,X+dx,Y+dy,width=1,fill=col)
            X += dx
        Y += dy


canvas.grid(column=0,row=0,rowspan=2)
combo.grid(row=1,column=1)
label.grid(row=0,column=1)
combo['values'] =  [1,2,3,4]
combo.bind('<<ComboboxSelected>>',painter)
combo.current(0)



painter(None)


root.mainloop()

I could change the painter function to include an infinite loop but this way I never reach the mainloop(), so I need to call this only after the main loop is created, but how?

Yotam
  • 10,295
  • 30
  • 88
  • 128
  • Could you provide some codes to show what you have done? – Sraw Oct 31 '17 at 08:48
  • 1
    you could call `after` repeatedly to draw the next frame of your animation, just be aware that if the `after` call may not trigger exactly when you want (it only guarantees that it will be called some time after the delay you specify) so your animation may appear jerky or the animation may be slower than desired – James Kent Oct 31 '17 at 08:59
  • @JamesKent, where do I add this after function? – Yotam Oct 31 '17 at 11:55

1 Answers1

2

a simple example of some animation using tkinter canvas:

import tkinter as tk

class App(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        self.title("Canvas animation example")

        self.c = tk.Canvas(self, width=400, height=400)
        self.c.pack()

        self.f_index = 0 # index so we know which frame to draw next
        # array to hold our frame data,
        # you'll probably need this to hold more than
        # just a set of coordinates to draw a line...
        self.f_data = [] 

        for num in range(0, 400, 5): # make up a set of fake data
            self.f_data.append([num, num, num+10, num+10])

    def next_frame(self):
        data = self.f_data[self.f_index] # fetch frame data
        self.c.delete('all') # clear canvas
        self.c.create_line(*data) # draw new frame data
        self.f_index += 1 # increment frame index
        if (self.f_index >= len(self.f_data)): # check and wrap if at end of sequence
            self.f_index = 0
        self.c.after(50, self.next_frame) # call again after 50ms

if __name__ == "__main__":
    app = App()
    app.next_frame() # called manually once to start animation
    # could be started with 'after' instead if desired
    app.mainloop()

note that the more items you want to delete and redraw the slower this code will perform. you need to have realistic expectations, drawing a few 10's of items will be fine, a few 100's might be ok on a decent pc, but 1000's of items would be very poorly performing.

James Kent
  • 5,763
  • 26
  • 50