为现有图形创建matplotlib交互式绘图窗口



我正在编写一个将曲线拟合到大型xy坐标数据集的程序。通过绘制和显示每次迭代的拟合过程,通常有助于观察算法的进展。我正在使用matplotlib来绘制。

我想做的是在主线程中创建图形,然后将其传递给显示它的子线程。这样我就可以在主线程中访问所有图形的方法和属性。我可以通过调用fig.gca().plot()来绘图,通过调用fig.canvas.draw()来绘图。

我不知道如何创建一个交互式绘图窗口,只显示我传递给它的图形。现在我正在使用matplotlib.pyplot.show(),它确实显示了我的图形,但它也显示了程序中可能定义的任何其他图形。是否有一种面向对象的方法来为特定的图形创建一个交互式窗口?我正在寻找一个不依赖于matplotlib中不支持的接口的解决方案。

这是一个类似的帖子,但它仍然没有回答我的问题:交互式图形与OO Matplotlib

我一直不明白为什么matplotlib似乎总是使用当前对象(当前图形,当前轴等)而不是特定对象(例如,为什么不使用matplotlib.pyplot.show(图)而不仅仅是show()?)我想我漏掉了什么。如果有人能告诉我为什么matplotlib是这样设计的,或者我是如何误解和/或滥用它的,那也将是感激的。

下面是我的代码:

import matplotlib.pyplot
import threading
import time
class Plotter():
    def __init__(self,fig):
        t = threading.Thread(target=self.PlottingThread,args=(fig,))
        t.start()       
    def PlottingThread(self,fig):
        #This line shows fig1 AND fig2 from below. I want it to show fig ONLY.
        matplotlib.pyplot.show()  
if __name__ == "__main__":
    fig1 = matplotlib.pyplot.figure()
    fig2 = matplotlib.pyplot.figure()
    Plotter(fig1)
    fig1.gca().clear()
    fig1.gca().plot([1,2,3])
    fig1.canvas.draw()

我想我明白了:

import Tkinter
import threading
import matplotlib.backends.backend_tkagg
root = Tkinter.Tk()
class Plotter():
    def __init__(self,fig):
        t = threading.Thread(target=self.PlottingThread,args=(fig,))
        t.start()       
    def PlottingThread(self,fig):        
        canvas = matplotlib.backends.backend_tkagg.FigureCanvasTkAgg(fig, master=root)
        canvas.show()
        canvas.get_tk_widget().pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1)
        toolbar = matplotlib.backends.backend_tkagg.NavigationToolbar2TkAgg(canvas, root)
        toolbar.update()
        canvas._tkcanvas.pack(side=Tkinter.TOP, fill=Tkinter.BOTH, expand=1)
        Tkinter.mainloop()
if __name__ == "__main__":
    import time
    fig1 = matplotlib.figure.Figure(figsize=(5,4), dpi=100)
    fig1.gca().plot([1,2,3])     
    fig2 = matplotlib.figure.Figure(figsize=(5,4), dpi=100)
    fig2.gca().plot([3,2,1])
    #Shows fig1 and not fig2, just like it's supposed to
    Plotter(fig1)
    time.sleep(1)
    #I can still plot to fig1 from my main thread
    fig1.gca().clear()
    fig1.gca().plot([5,2,7])
    fig1.canvas.draw()

唯一的问题是,如果您尝试创建两个Plotter实例,整个程序将崩溃。这对我的应用程序来说不是很重要,但这可能意味着我错误地使用了Tkinter。欢迎提出建议或更正

最新更新