如何使用计时器更新axvline?

问题描述

我想使用PyQt5为图制作动画,以便垂直线会随着时间在整个图形上滚动。 为了实现这一点,我开始修改this neat LearnPyQt tutorial中提供的代码示例。 到目前为止,我能够使用以下命令在用户定义的横坐标上绘制一条垂直线:

self.canvas.axes.axvline(x=5)

如果我使用的是for循环,我只会基于索引更新x,但是在这种情况下,我无法确定如何根据计时器ID更新x。如何恢复该值并将其传递到我的update_plot函数中?

到目前为止,这是我的代码

 import sys
 import random
 import matplotlib
 matplotlib.use('Qt5Agg')
 import pdb
 
 from PyQt5 import QtCore,QtWidgets
 
 from matplotlib.backends.backend_qt5agg import figureCanvasQTAgg as figureCanvas
 from matplotlib.figure import figure
 
 
 class MplCanvas(figureCanvas):
 
     def __init__(self,parent=None,width=5,height=4,dpi=100):
         fig = figure(figsize=(width,height),dpi=dpi)
         self.axes = fig.add_subplot(111)
         super(MplCanvas,self).__init__(fig)
 
 
 class MainWindow(QtWidgets.QMainWindow):
 
     def __init__(self,*args,**kwargs):
         super(MainWindow,self).__init__(*args,**kwargs)
 
         self.canvas = MplCanvas(self,dpi=100)
         self.setCentralWidget(self.canvas)
         self.timer_id = 0
         n_data = 50
         self.xdata = list(range(n_data))
         self.ydata = [random.randint(0,10) for i in range(n_data)]
         self.update_plot()
 
         self.show()
 

         self.timer = QtCore.QTimer()
         self.timer.setInterval(100)
 
         self.timer.timeout.connect(self.update_plot)
         self.timer.start()
 
     def update_plot(self):
 
         self.canvas.axes.plot(self.xdata,self.ydata,'r')
         self.canvas.axes.axvline(x=5)
         self.canvas.draw()
 
 
 app = QtWidgets.QApplication(sys.argv)
 w = MainWindow()
 app.exec_()

解决方法

如果保留对axvline(Line2D对象)的引用,则可以调用set_xdata并在调用self.timer_id时使update_plot递增以沿图中的直线移动。

class MainWindow(QtWidgets.QMainWindow):

    def __init__(self,*args,**kwargs):
        super(MainWindow,self).__init__(*args,**kwargs)

        self.canvas = MplCanvas(self,width=5,height=4,dpi=100)
        self.setCentralWidget(self.canvas)
        self.timer_id = 0
        n_data = 50
        self.xdata = list(range(n_data))
        self.ydata = [random.randint(0,10) for i in range(n_data)]
        self.update_plot()

        self.show()


        self.timer = QtCore.QTimer()
        self.timer.setInterval(100)

        self.timer.timeout.connect(self.update_plot)
        self.timer.start()

    def update_plot(self):
        if not self.timer_id:
            self.canvas.axes.plot(self.xdata,self.ydata,'r')
            self.vline = self.canvas.axes.axvline(x=self.timer_id)
        else:
            self.vline.set_xdata(self.timer_id)
        self.canvas.draw()
        self.timer_id += 1