如何使用 QTimer 更新另一个 class 中定义的 matplotlib FigureCanvas?

How to use QTimer to update a matplotlib FigureCanvas defined in another class?

我将 python3 与 PyQt5 和 matplotlib FigureCanvasQTAgg 一起使用。我需要每 1 秒更新一次绘图,所以我使用 QTimer。计时器正常工作,但情节未更新。这是代码:

main.py

import UI_action
from PyQt5.QtWidgets import QApplication
import sys

if __name__ == '__main__':
    app = QApplication(sys.argv)
    main_window = UI_action.Connection()
    main_window.show()

    sys.exit(app.exec_())

UI_action.py

import UI_layout_test
from PyQt5.QtWidgets import QWidget
import mplwidget


class Connection(QWidget):
    def __init__(self):
        super(Connection, self).__init__()
        self.my_widget_ui = UI_layout_test.Ui_MainWindow()
        self.my_widget_ui.setupUi(self)
        self.plot = mplwidget.Plot()
        self.my_widget_ui.pushButton_start.clicked.connect(self.__slot_start)


def __slot_start(self):
    self.plot.plot()

UI_layout_test.py(由 Qt Designer 生成)

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(692, 602)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.widget_fig = MplWidget(self.centralwidget)
        self.widget_fig.setGeometry(QtCore.QRect(30, 20, 631, 481))
        self.widget_fig.setObjectName("widget_fig")
        self.pushButton_start = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton_start.setGeometry(QtCore.QRect(550, 520, 113, 32))
        self.pushButton_start.setObjectName("pushButton_start")

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        self.pushButton_start.setText(_translate("MainWindow", "Start"))

from mplwidget import MplWidget

mplwidget.py

from PyQt5 import QtWidgets
from PyQt5 import QtCore
import matplotlib
matplotlib.use('Qt5Agg')

from matplotlib.figure import Figure
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from numpy import *


class MplCanvas(FigureCanvas):
    def __init__(self):
        self.fig = Figure(tight_layout=True)
        DPI = self.fig.get_dpi()
        self.fig.set_size_inches(850.0 / float(DPI), 720.0 / float(DPI))
        self.axis = self.fig.add_subplot(111, facecolor='white')

        self.axis.grid('on')
        self.axis.set_xlim(0, 10)
        self.axis.set_ylim(59.94, 60.06)
        self.axis.set_xlabel('Time (s)', fontsize=13)
        self.axis.set_ylabel('Frequency (Hz)', fontsize=13)

        FigureCanvas.__init__(self, self.fig)
        FigureCanvas.setSizePolicy(self, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Expanding)
        FigureCanvas.updateGeometry(self)


class MplWidget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        QtWidgets.QWidget.__init__(self, parent)   # Inherit from QWidget
        self.canvas = MplCanvas()                  # Create canvas object
        self.vbl = QtWidgets.QVBoxLayout()         # Set box for plotting
        self.vbl.addWidget(self.canvas)
        self.setLayout(self.vbl)


class Plot(MplWidget):
    def __init__(self):
        MplWidget.__init__(self)
        self.i = 0
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.plot)
        self.data = [59.98, 59.98, 59.99, 60, 60, 60, 60, 60]
        print('initialization complete')

    def plot(self):
        if self.i <= 8:
            self.canvas.axis.plot(self.data[:self.i], '*-')
            self.canvas.draw()
            print(self.data[:self.i])
            self.i += 1
            self.timer.start(1000)

输出为:

initialization complete
[]
[59.98]
[59.98, 59.98]
[59.98, 59.98, 59.99]
[59.98, 59.98, 59.99, 60]
[59.98, 59.98, 59.99, 60, 60]
[59.98, 59.98, 59.99, 60, 60, 60]
[59.98, 59.98, 59.99, 60, 60, 60, 60]
[59.98, 59.98, 59.99, 60, 60, 60, 60, 60]

根据输出,函数 plot 已被调用,计时器完成了它的工作。但是,图中没有显示图。我该如何解决?谢谢!

程序中有两个 MplWidget 实例。

  1. 第一个是UI_layout_test中的self.widget_fig = MplWidget(self.centralwidget)。这是 UI 中显示的那个,但它没有在代码中进一步使用。
  2. 第二个是在Connection中通过self.plot = Plot()创建的。这是通过计时器更新的那个,但它从未真正添加到小部件中。因此,您看不到应用于它的任何更改。

解决方案:决定其中一个并删除另一个。