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

时间:2018-03-21 18:47:38

标签: python matplotlib pyqt qtimer

我正在使用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并且计时器完成其工作。但是,图中没有显示情节。我该如何解决?谢谢!

1 个答案:

答案 0 :(得分:0)

程序中有MplWidget个实例。

  1. 第一个是来自self.widget_fig = MplWidget(self.centralwidget)的{​​{1}}。这是在UI中显示的那个,但它不会在代码中的任何地方使用。
  2. 第二个是UI_layout_testself.plot = Plot()创建的那个。这是通过计时器更新的,但它实际上从未添加到窗口小部件。因此,您没有看到应用任何更改。
  3. 解决方案:决定一个并删除另一个。