如何使用 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
实例。
- 第一个是
UI_layout_test
中的self.widget_fig = MplWidget(self.centralwidget)
。这是 UI 中显示的那个,但它没有在代码中进一步使用。
- 第二个是在
Connection
中通过self.plot = Plot()
创建的。这是通过计时器更新的那个,但它从未真正添加到小部件中。因此,您看不到应用于它的任何更改。
解决方案:决定其中一个并删除另一个。
我将 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
实例。
- 第一个是
UI_layout_test
中的self.widget_fig = MplWidget(self.centralwidget)
。这是 UI 中显示的那个,但它没有在代码中进一步使用。 - 第二个是在
Connection
中通过self.plot = Plot()
创建的。这是通过计时器更新的那个,但它从未真正添加到小部件中。因此,您看不到应用于它的任何更改。
解决方案:决定其中一个并删除另一个。