Как я могу обновить axvline с помощью таймера?

#python #timer #pyqt

#python #таймер #pyqt

Вопрос:

Я хотел бы использовать PyQt5 для анимации графика, чтобы вертикальная линия прокручивалась по моему рисунку с течением времени. Чтобы достичь этого, я начал изменять пример кода, приведенный в этом удобном руководстве по LearnPyQt. До сих пор мне удавалось построить единственную вертикальную линию по заданной пользователем оси абсцисс, используя:

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

Если бы я использовал for цикл, я бы просто обновил x на основе индекса, но в этом случае я не могу понять, как обновить 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, 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):
 
         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_()
  

Ответ №1:

Если вы сохраняете ссылку на 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
  

Комментарии:

1. Отлично! Большое спасибо, Алек! Я предполагаю, что я переосмыслил проблему: я думал о том, чтобы каким-то образом извлекать информацию о времени из timer метода, в то время как создание timer_id и увеличение его было самым простым способом. Еще раз спасибо!