【问题标题】:Matplotlib FuncAnimation does not update the plot embedded in wx PanelMatplotlib FuncAnimation 不更新嵌入在 wx Panel 中的绘图
【发布时间】:2018-08-28 13:34:03
【问题描述】:

我正在尝试使用 matplotlib FuncAnimation 更新带有串行数据的绘图。我正在使用以下示例将绘图嵌入到 wx 应用程序中。

Embedding a matplotlib figure inside a WxPython panel

但是,绘图并未更新,仅显示初始绘图。

事实上,update 函数永远不会被执行,它在 try 和 except 块中使用 print 语句进行检查。您可能会在此处看到脚本。

import wx

from matplotlib.figure import Figure as Fig
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wxagg import NavigationToolbar2WxAgg as NavigationToolbar

from collections import deque
import serial
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import matplotlib as mlp
import numpy as np

# Class that inherits wx.Panel. The purpose is to embed it into 
# a wxPython App. That part can be seen in main()
class Serial_Plot(wx.Panel):
    def __init__(self, parent, strPort, id=-1, dpi=None, **kwargs):
        super().__init__(parent, id=id, **kwargs)
        self.figure  = Fig(figsize=(20,20))
        self.ax = self.figure.add_subplot(111)
        self.canvas = FigureCanvas(self, -1, self.figure)
        self.plot_data, = self.ax.plot([1,2,3,4],[1,2,3,4])

        self.toolbar = NavigationToolbar(self.canvas)
        self.toolbar.Realize()

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.canvas, 1, wx.EXPAND)
        sizer.Add(self.toolbar, 0, wx.RIGHT | wx.EXPAND)
        self.SetSizer(sizer)
        self.Fit()
        # Serial communication
        self.ser = serial.Serial(strPort, 115200)
        # Serial data initialized as deque. The serial readings from arduino
        # are set to be one value per line.
        self.vals = deque()
        # matplotlib function animation
        anim = animation.FuncAnimation(self.figure, self.update, 
                                   interval=20)
        plt.show()
        self.close
    def update(self, i):
        try:
            print('trying')
            # read serial line
            data = float(self.ser.readline().decode('utf-8'))
            print(data)
            self.vals.append(data)
            # update plot data
            self.plot_data.set_data(range(len(self.vals)), self.vals)
        except:
            print('oops')
            pass
        return self.plot_data

    def close(self):
        # close serial
        self.ser.flush()
        self.ser.close()

def main():

    app = wx.App(False)
    frame = wx.Frame(None, -1, "WX APP!")
    demo_plot = Serial_Plot(frame,'COM3')
    frame.Show()
    app.MainLoop()

if __name__ == "__main__":
    main()

【问题讨论】:

    标签: python matplotlib wxpython


    【解决方案1】:

    正如我在之前的回答 (Embedding matplotlib FuncAnimation in wxPython: Unwanted figure pop-up) 中所说,尝试在 wxpython 中使用 animation.FuncAnimation()plt.show() 是行不通的,因为你有 2 个 main.loops。
    如果我们从您的原始问题中剔除所有 wx.python 并将其缩减为基础,我们会得到:

    from collections import deque
    import matplotlib.pyplot as plt
    import matplotlib.animation as animation
    import random
    vals = deque()
    figure  = plt.figure(figsize=(20,20))
    ax = plt.axes(xlim=(0, 1000), ylim=(0, 5000))
    plot_data, = ax.plot([], [])
    
    def update(i):
        data = float(random.randint(1000, 5000))
        vals.append(data)
        plot_data.set_data(range(len(vals)), vals)
        return plot_data
    
    anim = animation.FuncAnimation(figure, update, interval=20)
    plt.show()
    

    它之所以有效是因为animation 函数由plt.show() 控制,即matplotlib,但是一旦你引入了wxpython,它控制的是main.loop 而不是matplotlib。
    我相信您将不得不使用 wxpython timer 来控制串行设备读取,将数据输入绘图,如我之前的回答中所示。 Embedding matplotlib FuncAnimation in wxPython: Unwanted figure pop-up

    【讨论】:

      猜你喜欢
      • 2020-11-06
      • 2019-02-02
      • 1970-01-01
      • 2017-03-26
      • 1970-01-01
      • 2021-09-30
      • 2013-09-15
      • 1970-01-01
      相关资源
      最近更新 更多