【问题标题】:How to update a plot with python and Matplotlib如何使用 python 和 Matplotlib 更新绘图
【发布时间】:2011-07-06 20:14:14
【问题描述】:

我一直在努力尝试使用带有 python 和 wxpython 的 matplotlib 更新图形。我想按下一个按钮并将数据添加到嵌套在 wx.notebook 中的图形中。下面是代码。

感谢您的帮助

import wx
import matplotlib as mpl
import matplotlib.pyplot as plt
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas

class Plot(wx.Panel):
    def __init__(self, parent, id = -1, dpi = None, **kwargs):
        wx.Panel.__init__(self, parent, id=id, **kwargs)
        self.figure = mpl.figure.Figure(dpi=dpi, figsize=(2,2))
        self.canvas = Canvas(self, -1, self.figure)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas,1,wx.EXPAND)
        self.SetSizer(sizer)

class JBC(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title, size=(600,600))
        self.SetBackgroundColour(wx.Colour(236, 233, 216))

        self.nbG = wx.Notebook(self, -1, style=0, size=(400,400), pos=(0,0))       
        self.gSheet1 = self.add("Test").gca()

        calcButton = wx.Button(self, wx.NewId(), "Update", pos=(0, self.nbG.Position.y+400))

        #self.gSheet1.hold(False)
        #self.gSheet1.set_xlim(0,20)
        #self.gSheet1.set_ylim(0,20)
        #for i in range (2):
        #    self.gSheet1.plot([0,10],[1*i,1+i])

        #axes2 = plotter.add('figure 2').gca()
        #axes2.plot([1,2,3,4,5],[2,1,4,2,3])

        self.Bind(wx.EVT_BUTTON, self.OnCalculate, calcButton)

        self.Show(True)

    def OnCalculate(self, event):
        self.gSheet1.set_xlim(0,20)
        self.gSheet1.set_ylim(0,20)
        self.gSheet1.plot([1,2,3,4,5],[2,1,4,2,3])
        self.Update()

    def add(self,name="plot"):
       page = Plot(self.nbG)
       self.nbG.AddPage(page,name)
       return page.figure

    def Update(self):
        self.gSheet1.clear()
        plt.draw()
        print "Tried to redraw"


app = wx.App()
JBC(None, -1, "Test Title")
app.MainLoop()

【问题讨论】:

    标签: python wxpython matplotlib


    【解决方案1】:

    使用this example 作为指导,不妨试试这个:

    import wx
    import matplotlib as mpl
    mpl.use('WXAgg')
    import matplotlib.pyplot as plt
    from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as Canvas
    
    class Plot(wx.Panel):
        def __init__(self, parent, id = -1, dpi = None, **kwargs):
            wx.Panel.__init__(self, parent, id=id, **kwargs)
            self.figure = mpl.figure.Figure(dpi=dpi, figsize=(2,2))
            self.canvas = Canvas(self, -1, self.figure)
    
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(self.canvas,1,wx.EXPAND)
            self.SetSizer(sizer)
    
    class JBC(wx.Frame):
        def __init__(self, parent, id, title):
            wx.Frame.__init__(self, parent, id, title, size=(600,600))
            self.SetBackgroundColour(wx.Colour(236, 233, 216))
    
            self.nbG = wx.Notebook(self, -1, style=0, size=(400,400), pos=(0,0))       
            self.gSheet1 = self.add("Test").gca()
    
            calcButton = wx.Button(self, wx.NewId(), "Update", pos=(0, self.nbG.Position.y+400))
    
            #self.gSheet1.hold(False)
            #self.gSheet1.set_xlim(0,20)
            #self.gSheet1.set_ylim(0,20)
            #for i in range (2):
            #    self.gSheet1.plot([0,10],[1*i,1+i])
    
            #axes2 = plotter.add('figure 2').gca()
            #axes2.plot([1,2,3,4,5],[2,1,4,2,3])
    
            self.Bind(wx.EVT_BUTTON, self.OnCalculate, calcButton)        
            # self.Show(True)
    
        def OnCalculate(self, event):
            self.gSheet1.set_xlim(0,20)
            self.gSheet1.set_ylim(0,20)
            self.gSheet1.plot([1,2,3,4,5],[2,1,4,2,3])
            self.Update()
    
        def add(self,name="plot"):
           page = Plot(self.nbG)
           self.nbG.AddPage(page,name)
           return page.figure
    
        def Update(self):
            self.gSheet1.clear()
            plt.draw()
            print "Tried to redraw"
    
    if __name__ == '__main__':
        app = wx.App()
        frame=JBC(None, -1, "Test Title")
        frame.Show()
        app.MainLoop()
    

    也可以使用matplotlib来绘制动画人物:

    """
    Based on Tkinter bouncing ball code:
    http://stackoverflow.com/q/13660042/190597 (arynaq) and
    http://eli.thegreenplace.net/2008/08/01/matplotlib-with-wxpython-guis/
    """
    
    import wx
    import numpy as np
    import matplotlib.pyplot as plt
    import matplotlib.figure as mplfig
    import scipy.spatial.distance as dist
    import matplotlib.backends.backend_wxagg as mwx
    
    class Frame(wx.Frame):
        def __init__(self):
            wx.Frame.__init__(self, None, wx.ID_ANY, size = (800, 600))
            self.panel = wx.Panel(self)        
            self.fig = mplfig.Figure(figsize = (5, 4), dpi = 100)
            self.ax = self.fig.add_subplot(111)
            self.vbox = wx.BoxSizer(wx.VERTICAL)        
            self.canvas = mwx.FigureCanvasWxAgg(self.panel, wx.ID_ANY, self.fig)
            self.toolbar = mwx.NavigationToolbar2WxAgg(self.canvas)
            self.button = wx.Button(self.panel, wx.ID_ANY, "Quit")
            self.vbox.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
            self.vbox.Add(self.toolbar, 0, wx.EXPAND)        
            self.vbox.Add(
                self.button, 0, border = 3,
                flag = wx.ALIGN_LEFT | wx.ALL | wx.ALIGN_CENTER_VERTICAL)
            self.panel.SetSizer(self.vbox)
            self.vbox.Fit(self)
            self.toolbar.update()
            self.update = self.animate().next
            self.timer = wx.Timer(self)
            self.timer.Start(1)
            self.Bind(wx.EVT_BUTTON, self.OnCloseWindow, self.button)        
            self.Bind(wx.EVT_TIMER, lambda event: self.update())
            self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
    
        def OnCloseWindow(self, evt):
            self.timer.Stop()
            del self.timer
            self.Destroy()
    
        def animate(self):
            N = 100                                             #Number of particles
            R = 10000                                           #Box width
            pR = 5                                               #Particle radius
    
            r = np.random.randint(0, R, (N, 2))                  #Position vector
            v = np.random.randint(-R/100, R/100, (N, 2))           #velocity vector
            a = np.array([0, -10])                               #Forces
            v_limit = R/2                                       #Speedlimit
    
            line, = self.ax.plot([], 'o')
            line2, = self.ax.plot([], 'o')                           #Track a particle
            self.ax.set_xlim(0, R+pR)
            self.ax.set_ylim(0, R+pR)        
    
            while True:
                v = v+a                                           #Advance
                r = r+v
    
                #Collision tests
                r_hit_x0 = np.where(r[:, 0]<0)                   #Hit floor?
                r_hit_x1 = np.where(r[:, 0]>R)                   #Hit roof?
                r_hit_LR = np.where(r[:, 1]<0)                   #Left wall?
                r_hit_RR = np.where(r[:, 1]>R)                   #Right wall?
    
                #Stop at walls
                r[r_hit_x0, 0] = 0
                r[r_hit_x1, 0] = R
                r[r_hit_LR, 1] = 0
                r[r_hit_RR, 1] = R
    
                #Reverse velocities
                v[r_hit_x0, 0] = -0.9*v[r_hit_x0, 0]
                v[r_hit_x1, 0] = -v[r_hit_x1, 0]
                v[r_hit_LR, 1] = -0.95*v[r_hit_LR, 1]
                v[r_hit_RR, 1] = -0.99*v[r_hit_RR, 1]
    
                #Collisions
                D = dist.squareform(dist.pdist(r))
                ind1, ind2 = np.where(D < pR)
                unique = (ind1 < ind2)
                ind1 = ind1[unique]
                ind2 = ind2[unique]
    
                for i1, i2 in zip(ind1, ind2):
                    eps = np.random.rand()
                    vtot = v[i1, :]+v[i2, :]
                    v[i1, :] = -(1-eps)*vtot
                    v[i2, :] = -eps*vtot
    
                line.set_ydata(r[:, 1])
                line.set_xdata(r[:, 0])
                line2.set_ydata(r[:N/5, 1])
                line2.set_xdata(r[:N/5, 0])
                self.canvas.draw()
                yield True
    
    def main():
        app = wx.App(False)
        frame = Frame()
        frame.Show(True)
        app.MainLoop()
    
    if __name__ == '__main__':
        main()
    

    【讨论】:

    猜你喜欢
    • 2018-04-28
    • 1970-01-01
    • 1970-01-01
    • 2011-05-05
    • 2011-03-31
    • 2018-03-13
    相关资源
    最近更新 更多