Animation of a color plot with playback, pause, stop using Tkinter with pylab / matplotlib attachment: cannot update figure / canvas?

I looked, but did not find the previous tasks enough, so sorry if this happens again. Purpose: a graphical interface for continuous updating of a figure with various matrix data plotted by pylab pcolor, so that there is a working animation. But the user should be able to play, pause, stop the animation using the buttons on the Tkinter widget.

Before getting the answer on matplotlib using set_array (), draw () and canvas.manager.after () ... I have a working code that allows me to start the animation, but I cannot figure out how to stop or pause its just using the capabilities of matplotlib, so I decided to use the Tkinter straigt instead of the matplotlib Tcl / Tk wrapper. Here is a working code for strikes only, although in case someone has ideas. But continue for real.

# mouse click the "Play" button widget to play animation # PROBLEMS: # 1. can't pause or stop animation. once loop starts it cant be broken # 2. set_array attribute for pcolor PolyCollection object only updates the matrix # C of pcolor, however for my actual application, I will be using pcolor(x,y,C) # and will have new x,y, and C per plot. Unlike line object, where set_xdata and # set_ydata are used, I can't find an analogy to pcolor. If I were updating an # image I could use set_data(x,y,C), but i am not importing an image. I assume # pcolor is still my best bet unless (as in Matlab) there is an equivalent # image(x,y,C) function? import time as t from pylab import * from matplotlib.widgets import Button ion() def pressPlay(event): #fig=figure() ax = subplot(111) subplots_adjust(bottom=0.2) c=rand(5,5) cplot=pcolor(c) draw() for i in range(5): c=rand(5,5) cplot.set_array(c.ravel()) cplot.autoscale() title('Ionosphere '+str(i+1)) t.sleep(3) draw() axPlay = axes([0.7, 0.05, 0.1, 0.075]) bPlay = Button(axPlay, 'Play') bPlay.on_clicked(pressPlay) 

Btw: when importing pylab, the TkAgg database is automatically installed for use in matplotlib ... I think. Or somehow I automatically use TkAgg. I am running Linux, Python 2.6.4, Ipython 0.10.

I manipulated the code found in the Daniweb IT Discussion Community to use the Tkinter and update_idletasks () function, which I can play, pause, stop changing the colors of the shortcut widget. This can only be run on one python while Tkinter is installed. No use of matplotlib or pylab. This is the working code and the basis of the final code that I am setting.

 # This is meant to draw Start and Stop buttons and a label # The Start button should start a loop in which the label # is configured to change color by looping through a color list. # At each pass through the loop the variable self.stop is checked: # if True the loop terminates. # The Stop button terminates the loop by setting the # variable self.stop to True. # The Start button restarts the animation from the beginning # if Stop was hit last, or restarts the animation from where it left off # if pause was hit last. # The loop also terminates on the last color of the list, as if stop were hit from Tkinter import * colors = ['red','green','blue','orange','brown','black','white','purple','violet'] numcol=len(colors) class SGWidget(Frame): def __init__(self, parent=None): Frame.__init__(self, parent) self.top_frame = Frame(bg='green') self.top_frame.grid() # enter event loop until all idle callbacks have been called. self.top_frame.update_idletasks() self.makeToolbar() # construct a label widget with the parent frame top_frame self.label = Label(self.top_frame,text = 'Text',bg='orange') self.label.grid() # initialize (time index t) self.t=0 def makeToolbar(self): self.toolbar_text = ['Play','Pause','Stop'] self.toolbar_length = len(self.toolbar_text) self.toolbar_buttons = [None] * self.toolbar_length for toolbar_index in range(self.toolbar_length): text = self.toolbar_text[toolbar_index] bg = 'yellow' button_id = Button(self.top_frame,text=text,background=bg) button_id.grid(row=0, column=toolbar_index) self.toolbar_buttons[toolbar_index] = button_id def toolbar_button_handler(event, self=self, button=toolbar_index): return self.service_toolbar(button) # bind mouse click on start or stop to the toolbar_button_handler button_id.bind("<Button-1>", toolbar_button_handler) # call blink() if start and set stop when stop def service_toolbar(self, toolbar_index): if toolbar_index == 0: self.stop = False print self.stop self.blink() elif toolbar_index == 1: self.stop = True print self.stop elif toolbar_index == 2: self.stop = True print self.stop self.t=0 # while in start, check if stop is clicked, if not, call blink recursivly def blink(self): if not self.stop: print 'looping',self.stop self.label.configure(bg=colors[self.t]) self.t += 1 if self.t == numcol: # push stop button self.service_toolbar(2) self.label.update_idletasks() self.after(500, self.blink) if __name__ == '__main__': SGWidget().mainloop() 

Then, using the matplotlib embedding_in_tk.html example, http://matplotlib.sourceforge.net/examples/user_interfaces/embedding_in_tk.html , I manipulated the previous code to animate the canvas associated with the pcolor figure. However, updating the canvas with canvas.get_tk_widget () does not do the trick I assume due to the command in front of it that renders pcolor () again. So I assume that every time I redo the plot, I need to reconnect the canvas with the figure? But I do not know how to do this. Hope I'm even on the right track using update_idletasks () ???

So, with the following code, all I see is the same plot when the code iterates through Play instead of an updated digit? This is my main problem and question.

 from pylab import * from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg from Tkinter import * colors=[None]*10 for i in range(len(colors)): colors[i]=rand(5,5) #colors = ['red','green','blue','orange','brown','black','white','purple','violet'] numcol=len(colors) class App(Frame): def __init__(self,parent=None): Frame.__init__(self,parent) self.top=Frame() self.top.grid() self.top.update_idletasks() self.makeWidgets() self.makeToolbar() def makeWidgets(self): # figsize (w,h tuple in inches) dpi (dots per inch) #f = Figure(figsize=(5,4), dpi=100) self.f = Figure() self.a = self.f.add_subplot(111) self.a.pcolor(rand(5,5)) # a tk.DrawingArea self.canvas = FigureCanvasTkAgg(self.f, master=self.top) self.canvas.get_tk_widget().grid(row=3,column=0,columnspan=3) self.bClose = Button(self.top, text='Close',command=self.top.destroy) self.bClose.grid() #self.label = Label(self.top, text = 'Text',bg='orange') #self.label.grid() # initialize (time index t) self.t=0 def makeToolbar(self): self.toolbar_text = ['Play','Pause','Stop'] self.toolbar_length = len(self.toolbar_text) self.toolbar_buttons = [None] * self.toolbar_length for toolbar_index in range(self.toolbar_length): text = self.toolbar_text[toolbar_index] bg = 'yellow' button_id = Button(self.top,text=text,background=bg) button_id.grid(row=0, column=toolbar_index) self.toolbar_buttons[toolbar_index] = button_id def toolbar_button_handler(event, self=self, button=toolbar_index): return self.service_toolbar(button) button_id.bind("<Button-1>", toolbar_button_handler) # call blink() if start and set stop when stop def service_toolbar(self, toolbar_index): if toolbar_index == 0: self.stop = False print self.stop self.blink() elif toolbar_index == 1: self.stop = True print self.stop elif toolbar_index == 2: self.stop = True print self.stop self.t=0 # while in start, check if stop is clicked, if not, call blink recursivly def blink(self): if not self.stop: print 'looping',self.stop self.a.pcolor(colors[self.t]) #draw() #self.label.configure(bg=colors[self.t]) self.t += 1 if self.t == numcol: # push stop button self.service_toolbar(2) self.canvas.get_tk_widget().update_idletasks() #self.label.update_idletasks() self.after(500, self.blink) #root = Tk() app=App() app.mainloop() 

Thanks for the help!

+4
source share
1 answer

In your blink function, add self.canvas.show() before self.canvas.show() unoccupied tasks:

 self.canvas.show() # insert this line self.canvas.get_tk_widget().update_idletasks() 
+2
source

Source: https://habr.com/ru/post/1316363/


All Articles