I am using python3 with PyQt5 and matplotlib FigureCanvasQTAgg. I need to update a plot every 1 second, so I use QTimer. The timer works properly, but the plot is not updated. Here is the code:
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 (generated by 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)
The output is:
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]
Based on the output, the function plot
has been called and the timer did its job. However, there was no plot shown on the figure. How do I fix this? Thanks!
There are two instances of MplWidget
in the programme.
self.widget_fig = MplWidget(self.centralwidget)
from the UI_layout_test
. This is the one which is shown in the UI, but it is not used anywhere further in the code.self.plot = Plot()
inside Connection
. This the one which is updated via the timer, but it is never actually added to the widget. Hence you do not see any of the changes applied to it. Solution: Decide for one those and remove the other.