4

私は見ましたが、以前の質問が十分に具体的ではなかったので、これが繰り返されたら申し訳ありません. 目標: 実行中のアニメーションがあるように、pylab の pcolor によってプロットされたさまざまな行列データで Figure を継続的に更新する GUI。ただし、ユーザーは Tkinter ウィジェットのボタンでアニメーションを再生、一時停止、停止できる必要があります。

set_array()、draw()、および canvas.manager.after() を使用して matplotlib の回答を得る前に ...、アニメーションを開始できるようにする作業コードがありますが、停止または停止する方法がわかりませんmatplotlib の機能だけを使用する場合は一時停止するため、matplotlib の Tcl/Tk ラッパーの代わりに Tkinter straigt up を使用することにしました。誰かがアイデアを持っている場合に備えて、キックのためだけに動作するコードを次に示します。しかし、本当の質問を続けます。

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

ところで:pylabをインポートすると、TkAggバックエンドはmatplotlibで使用するように自動的に設定されます...と思います。または、どういうわけか自動的に TkAgg を使用します。Linux、Python 2.6.4、Ipython 0.10 を実行しています。

Daniweb IT ディスカッション コミュニティから見つけたコードを操作して、Tkinter と update_idletasks() 関数を使用して、ラベル ウィジェットの色の変化を再生、停止、停止できるようにしました。これは、Tkinter がインストールされている限り、Python だけで実行できます。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()

助けてくれてありがとう!

4

1 に答える 1

2

self.canvas.show()点滅機能で、アイドル タスクを呼び出す前に a を追加します。

self.canvas.show() # insert this line
self.canvas.get_tk_widget().update_idletasks()
于 2010-07-21T01:06:04.640 に答える