我正在尝试使用matplotlib FuncAnimation用串行数据更新绘图。我正在使用以下示例将情节嵌入wx应用程序中。
Embedding a matplotlib figure inside a WxPython panel
实际上,永远不会执行更新功能,该更新功能将在try和except块中使用打印语句进行检查。您可能会在这里看到脚本。
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()
答案 0 :(得分:0)
正如我在上一个答案(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