2010-07-20 1 views
4

Я посмотрел, но не нашел ответы на предыдущие вопросы достаточно, так что извините, если это повторяется. Цель: графический интерфейс для непрерывного обновления фигуры с различными данными матрицы, нанесенными pcolab pylab, так что есть работающая анимация. Но пользователь должен иметь возможность проигрывать, приостанавливать, останавливать анимацию с помощью кнопок виджета Tkinter.цветная анимация сюжета с воспроизведением, пауза, остановка с помощью Tkinter с вложением pylab/matplotlib: невозможно обновить фигуру/холст?

Прежде чем получить ответ на matplotlib с помощью set_array(), draw() и canvas.manager.after() ..., у меня есть рабочий код, который позволяет мне запускать анимацию, но я не могу понять как остановить или приостановить его, просто используя возможности matplotlib, поэтому я решил использовать Tkinter straigt вместо оболочки Tcl/Tk matplotlib. Вот рабочий код только для ударов, хотя в случае, если у кого-то есть идеи. Но продолжайте заниматься реальным вопросом.

# 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: в импорте pylab в TkAgg бэкенд автоматически устанавливается для использования в Matplotlib ... я думаю. Или как-то я автоматически использую TkAgg. Я запускаю Linux, Python 2.6.4, Ipython 0.10.

Я манипулировал кодом, найденным в сообществе Daniweb IT Discussion Community, чтобы с помощью Tkinter и функции update_idletasks() я мог играть, прерывать, меняя цвета виджета ярлыков. Это можно запустить только на одном python, пока установлен Tkinter. Нет использования matplotlib или pylab. Это рабочий код и костяк последнего кода, который я задаю.

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

Затем, с помощью Matplotlib например embedding_in_tk.html, http://matplotlib.sourceforge.net/examples/user_interfaces/embedding_in_tk.html, я манипулировали предыдущий код для анимации холст, подключенный к pcolor фигуре. Тем не менее, обновление холста с помощью canvas.get_tk_widget() не делает трюк, который я предполагаю из-за команды перед ним, которая повторно отображает pcolor(). Так что я предполагаю, что каждый раз, когда я переделываю сюжет, мне нужно снова подключить холст с фигурой? Но я не знаю, как это сделать. Надеюсь, я даже на правильном пути, используя update_idletasks() ???

Итак, со следующим кодом, все, что я вижу, это тот же сюжет, когда код перебирает через Play вместо обновленной цифры? Это моя главная проблема и вопрос.

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

Спасибо за помощь!

ответ

2

В функции мигания, добавьте self.canvas.show() перед вызовом праздных задач:

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

Вау, это было легко! Я использовал show() много раз в конце скриптов, но я не понимал, что это также индивидуальный метод холста. Спасибо! – AmyS

+0

ars, я отправлю другой вопрос со ссылкой на этот вопрос, но в случае, если вы можете ответить ... Если я хочу анимировать контуры вместо этого, если цветной график, если я просто изменил команду построения графика: self.a .contour (colors [self.t]) показаны контурные сюжеты, но вместо того, чтобы обновлять холст в качестве нового сюжета каждый раз, как это сделал pcolor, они переоценивают себя. Знаете ли вы, как я могу очистить предыдущие контурные сюжеты, не используя очевидную cla(), чтобы я не видел белый? спасибо – AmyS

+0

хорошо, если я сам.a.cla() прямо перед self.a.contour() я на самом деле не вижу прозрачную полосу перед следующим графиком, поэтому он работает. Но, если есть лучший способ установить анимацию, чем cla(), я бы предпочел бы ее, потому что у меня также будут другие данные на моем сюжете, и я не обязательно хочу ее очистить. Кроме того, я буду использовать self.a.plot(), но, похоже, это точный сценарий как контур() – AmyS

 Смежные вопросы

  • Нет связанных вопросов^_^