简体   繁体   中英

Matplotlib FuncAnimation does not update the plot embedded in wx Panel

I am trying to update a plot with serial data with matplotlib FuncAnimation. I am using the following example to embed the plot in a wx app.

Embedding a matplotlib figure inside a WxPython panel

However, the plot is not updated and only the initial plot is displayed. 在此处输入图片说明

In fact, the update function is never executed which is checked with print statements in try and except blocks. You may see the script here.

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

As I said in my previous answer( Embedding matplotlib FuncAnimation in wxPython: Unwanted figure pop-up ), trying to use animation.FuncAnimation() and plt.show() within wxpython is not going to work, because you have 2 main.loops.
If we cull all of the wx.python from your original question and pare it down to the basics, we get this:

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

在此处输入图片说明

It works because the animation function is controlled by plt.show() ie matplotlib but once you introduce wxpython, it controls the main.loop not matplotlib.
I believe that you will have to use a wxpython timer to control the serial device read, feeding data into the plot, as demonstrated in my previous answer. Embedding matplotlib FuncAnimation in wxPython: Unwanted figure pop-up

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM