[英]How can I update a matplotlib figure in a way that prevents xdata from being None?
我正在编写一个应用程序,该应用程序定期(大约每秒一次)从硬件设备收集一些数据,并使用matplotlib将其显示在图形中。 用户将定期单击图形,当发生这种情况时,我需要知道图形的坐标系中测量的单击的x和y坐标。
这很容易做到:如果canvas
是FigureCanvas
实例,则可以说
canvas.mpl_connect('button_release_event', mouse_up_handler)
并定义
def mouse_up_handler(event):
print('The user clicked at ({}, {})'.format(event.xdata, event.ydata))
以在图形的坐标系中显示点击坐标。 但是,有时用户会在图形更新时单击鼠标右键,然后event.xdata
和.ydata
为None
。 现在,我只是舍弃这些点击,但是当应用程序忽略他们的点击时,这显然让用户感到沮丧。
我已经附上了完整的示例程序,以便您可以看到如何用新的图形替换当前的图形。 (如果运行它并重复单击图形,您有时会看到报告的x坐标有时为None
。)我可以用永远不会给出None
的方式替换图形的数据吗? 我只希望一次显示一组数据。
from __future__ import print_function
from math import exp
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg \
as FigureCanvas
from matplotlib.figure import Figure
from random import normalvariate
from threading import Timer
from time import sleep
import wx
class GraphView(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.figure = Figure()
canvas = FigureCanvas(self, -1, self.figure)
canvas.mpl_connect('button_release_event', self.mouse_up_handler)
self.axes = None
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(canvas, 1, wx.GROW)
self.SetSizer(sizer)
self.generate_new_data()
def generate_new_data(self):
x_values = range(16384)
y_values = [exp(normalvariate(0, 10)) for _ in range(16384)]
if self.axes is not None:
self.figure.delaxes(self.axes)
sleep(0.4) # simulate some additional work being done with the data
self.axes = self.figure.add_subplot(1, 1, 1)
self.axes.set_yscale('log')
self.axes.autoscale(enable=True)
self.axes.set_xlim(x_values[0], x_values[-1])
self.axes.plot(x_values, y_values, antialiased=False)
self.figure.canvas.draw()
Timer(1.0, self.generate_new_data).start()
def mouse_up_handler(self, event):
print('Click at x = {}'.format(event.xdata))
class GraphWindow(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent)
graph_view = GraphView(self)
if __name__ == '__main__':
app = wx.App(False)
GraphWindow(None).Show()
app.MainLoop()
就像是:
def __init__(self, parent):
wx.Panel.__init__(self, parent)
self.figure = Figure()
canvas = FigureCanvas(self, -1, self.figure)
canvas.mpl_connect('button_release_event', self.mouse_up_handler)
# make axes
self.ax = self.figure.add_subplot(1, 1, 1)
# set up details
self.ax.set_yscale('log')
self.ax.autoscale(enable=True)
self.ax.set_xlim(x_values[0], x_values[-1])
# make the line
self.ln, = self.ax.plot([], []) # add what ever parameters you want
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(canvas, 1, wx.GROW)
self.SetSizer(sizer)
self.generate_new_data()
def generate_new_data(self):
x_values = range(16384)
y_values = [exp(normalvariate(0, 10)) for _ in range(16384)]
sleep(0.4) # simulate some additional work being done with the data
# update your existing line
self.ln.set_data(x_values, y_values, antialiased=False)
self.figure.canvas.draw()
Timer(1.0, self.generate_new_data).start()
重用轴和Line2D
对象。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.