Tkinter中的Matplotlib动画图

问题描述 投票:0回答:1

我真的很在意使用FuncAnimation和Tkinter进行实时绘图。我不确定重现该问题需要什么信息。如果有任何遗漏,请原谅我。在精简版中,它可以正常工作:

from numpy.random import normal
from numpy import exp
def fn(x):
    A=3e-8
    B=6e3
    Inoise = 1e-10
    if x == 0:
        I = Inoise
    elif A*x**2*exp(-B/x) < Inoise:
        I = Inoise
    else:
        I = A*x**2*exp(-B/x)
    return normal(1,0.4,1)[0]*I

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg,NavigationToolbar2Tk
from matplotlib.animation import FuncAnimation
from matplotlib.pyplot import Figure
from tkinter import Frame

from queue import Queue
class LivePlotWindow(Frame):
    def __init__(self, master,xlabel='',ylabel='',logx=False,logy=False):
        Frame.__init__(self, master)
        self.pack(fill='both', expand=1)     
        self.fig = Figure()
        self.ax = self.fig.add_subplot(111)
        self.canvas = FigureCanvasTkAgg(self.fig, master=self)   
        self.toolbar = NavigationToolbar2Tk(self.canvas, self)
        self.toolbar.update()
        self.canvas.get_tk_widget().pack()
        self.xlabel = xlabel
        self.ylabel = ylabel
        self.logx = logx
        self.logy = logy
        self.q = Queue()
        self._axini()

    def _axini(self):
        self.ax.cla()
        self.ax.set_xlabel(self.xlabel)
        self.ax.set_ylabel(self.ylabel)
        if self.logx==True:
            self.ax.set_xscale('log', nonposx='clip')
        if self.logy==True:
            self.ax.set_yscale('log', nonposy='clip')
        self.fig.tight_layout()

    def _update(self,i):
        print(i)
        [x,y] = self.q.get(block=True) 
        print([x,y])
        self.ax.plot(x,y,'b.')  # update the data

    def run(self,ncalls):
        self._axini()
        print(ncalls)   
        self.ani = FuncAnimation(self.fig, self._update, range(ncalls-1), interval=100, repeat=False)
        print(ncalls)

    def addP(self,x,y):
        self.q.put([x,y])

    def stop(self):
        self.ani.event_source.stop()

from tkinter import Tk
root = Tk()
root.title('Kennlinien-Messprogramm')
root.geometry('700x500')
plot = LivePlotWindow(root,'Voltage in V','Current in A',logy=True)

n=100
plot.run(n)
for i in range(n):
    plot.addP(i*10,fn(i*10))
root.mainloop()

但是当我将它集成到带有菜单的GUI中时,它只是不调用动画函数。似乎当我将Plot对象作为命令调用传递时,它不再起作用了吗?如果我直接调用启动函数,它会出错。我不知道为什么:

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg,NavigationToolbar2Tk
from matplotlib.animation import FuncAnimation
from matplotlib.pyplot import Figure
from tkinter import Tk,Frame,Menu

from queue import Queue
class LivePlotWindow(Frame):
    def __init__(self, master,xlabel='',ylabel='',logx=False,logy=False):
        Frame.__init__(self, master)
        self.pack(fill='both', expand=1)     
        self.fig = Figure()
        self.ax = self.fig.add_subplot(111)
        self.canvas = FigureCanvasTkAgg(self.fig, master=self)   
        self.toolbar = NavigationToolbar2Tk(self.canvas, self)
        self.toolbar.update()
        self.canvas.get_tk_widget().pack()
        self.xlabel = xlabel
        self.ylabel = ylabel
        self.logx = logx
        self.logy = logy
        self.q = Queue()
        self._axini()

    def _axini(self):
        self.ax.cla()
        self.ax.set_xlabel(self.xlabel)
        self.ax.set_ylabel(self.ylabel)
        if self.logx==True:
            self.ax.set_xscale('log', nonposx='clip')
        if self.logy==True:
            self.ax.set_yscale('log', nonposy='clip')
        self.fig.tight_layout()

    def _update(self,i):
        print(i)
        [x,y] = self.q.get(block=True) 
        print([x,y])
        self.ax.plot(x,y,'b.')  # update the data

    def run(self,ncalls):
        self._axini()
        print(ncalls)   
        self.ani = FuncAnimation(self.fig, self._update, range(ncalls-1), interval=100, repeat=False)
        print(ncalls)

    def addP(self,x,y):
        self.q.put([x,y])

    def stop(self):
        self.ani.event_source.stop()

from tkinter import Tk
root = Tk()
root.title('Kennlinien-Messprogramm')
root.geometry('700x500')
plot = LivePlotWindow(root,'Voltage in V','Current in A',logy=True)

def start(menu,plot):
    menu.entryconfig('\u25B6', state='disabled')
    menu.entryconfig('\u25A0', state='normal')
    n=100
    plot.run(n)
    for i in range(n):
        plot.addP(i*10,fn(i*10))

def stop(menu,plot):
    plot.stop
    menu.entryconfig('\u25B6', state='normal')
    menu.entryconfig('\u25A0', state='disabled')

menu = Menu(root)
root.config(menu=menu)
menu.add_command(label='\u25B6', command=lambda: start(menu,plot))
#menu.entryconfig(1, fg='green')
menu.add_command(label='\u25A0', command=lambda: stop(menu,plot))
menu.entryconfig('\u25A0', state='disabled')

#start(menu,plot)

root.mainloop()

任何帮助将不胜感激! ;)

python matplotlib animation tkinter
1个回答
0
投票

我已经找到了解决方案,尽管我不知道它有多聪明...现在,我连续地绘制xdata和ydata。自从我传递了引用以来,它就更新了图类之外的所有更改。但是,我每次都重新绘制孔图...

from tkinter import Frame
from matplotlib.pyplot import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.animation import FuncAnimation
class LivePlotWindow(Frame):
    def __init__(self, master, xdata, ydata, xlabel='',ylabel='',logx=False,logy=False):
        Frame.__init__(self, master)
        self.pack(fill='both', expand=1)     
        self.fig = Figure()
        self.ax = self.fig.add_subplot(111)
        self.ax.set_xlabel(xlabel)
        self.canvas = FigureCanvasTkAgg(self.fig, master=self)   
        self.canvas.get_tk_widget().pack()
        self.xdata = xdata
        self.ydata = ydata
        self.xlabel = xlabel
        self.ylabel = ylabel
        self.logx = logx
        self.logy = logy
        self.ani = FuncAnimation(self.fig, self._update, interval=500)

    def _update(self,i):
        self.ax.cla()
        self.ax.set_xlabel(self.xlabel)
        self.ax.set_ylabel(self.ylabel)
        if self.logx:
            self.ax.set_xscale('log', nonposx='clip')
        if self.logy:
            self.ax.set_yscale('log', nonposy='clip')
        #if self.millikan:
        #    self.ax.plot(1/self.xdata,self.ydata)
        #else:
        self.ax.plot(self.xdata,self.ydata,'b.')  # update the data
        self.fig.tight_layout()
最新问题
© www.soinside.com 2019 - 2024. All rights reserved.