[英]Dynamically update matplotlib canvas in a pyqt5 interface
我有一個非常簡單的程序,必須保留結構(這是練習的條件)。
我們從一個按鈕和一個Canvas組成的界面開始,如上圖所示。
單擊該按鈕后,將啟動一個后台任務,該任務將調用一個名為animation
的函數。 在這里,我們開始一個過程,每次waiting_time
生成隨機數據。 每當有新的x和y變量時,我們要更新圖。
代碼如下:
from PyQt5 import QtCore, QtWidgets
from mplwidget import MplWidget
import threading
import time
import numpy as np
import sys
class RandomDataGeneration():
"""
Mandatory Class. This Class must exist.
"""
def __init__(self):
pass
def data_generation(self):
while True:
waiting_time = np.random.randint(1,4) # waiting time is given by a random number.
print(waiting_time)
time.sleep(waiting_time)
self.x = np.random.rand(10)
self.y = np.random.rand(10)
print(self.x)
print(self.y)
#self.update_plot()
def update_plot(self):
self.MplWidget.canvas.axes.clear()
self.MplWidget.canvas.axes.set_title('GRAPH')
self.MplWidget.canvas.axes.plot(x, y, marker='.', linestyle='')
self.MplWidget.canvas.axes.legend(('random'), loc='upper right')
self.MplWidget.canvas.draw()
def animation():
"""
This function initiates the RandomDataGeneration
"""
app = RandomDataGeneration()
app.data_generation()
class Ui_MainWindow():
def __init__(self):
super().__init__()
def start_download(self):
download_info = threading.Thread(target=animation)
download_info.start()
def setupUi(self, MainWindow):
MainWindow.setObjectName("MainWindow")
MainWindow.resize(1280, 1024)
self.centralwidget = QtWidgets.QWidget(MainWindow)
self.centralwidget.setObjectName("centralwidget")
self.pushButton = QtWidgets.QPushButton(self.centralwidget)
self.pushButton.setGeometry(QtCore.QRect(880, 80, 221, 32))
self.pushButton.setObjectName("pushButton")
self.MplWidget = MplWidget(self.centralwidget)
self.MplWidget.setGeometry(QtCore.QRect(49, 39, 771, 551))
self.MplWidget.setObjectName("MplWidget")
MainWindow.setCentralWidget(self.centralwidget)
self.retranslateUi(MainWindow)
QtCore.QMetaObject.connectSlotsByName(MainWindow)
def retranslateUi(self, MainWindow):
_translate = QtCore.QCoreApplication.translate
MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
self.pushButton.setText(_translate("MainWindow", "PushButton"))
self.pushButton.clicked.connect(self.start_download)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
MainWindow = QtWidgets.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())
要運行該代碼,必須在同一文件夾中包含名稱為mplwidget.py
的以下代碼。
# ------------------------------------------------------
# -------------------- mplwidget.py --------------------
# ------------------------------------------------------
from PyQt5.QtWidgets import*
from matplotlib.backends.backend_qt5agg import FigureCanvas
from matplotlib.figure import Figure
class MplWidget(QWidget):
def __init__(self, parent = None):
QWidget.__init__(self, parent)
self.canvas = FigureCanvas(Figure())
vertical_layout = QVBoxLayout()
vertical_layout.addWidget(self.canvas)
self.canvas.axes = self.canvas.figure.add_subplot(111)
self.setLayout(vertical_layout)
由於您正在創建pyqt5應用程序,所以我猜您最好的選擇是對阻塞部分使用QThread
並在每次生成新數據時發出信號。 一種方法是使RandomDataGeneration
作為QThread
的子類並實現run
,例如
class RandomDataGeneration(QtCore.QThread):
"""
Mandatory Class. This Class must exist.
"""
new_data = QtCore.pyqtSignal()
def __init__(self, parent = None):
super().__init__(parent)
def data_generation(self):
while True:
waiting_time = np.random.randint(1,4) # waiting time is given by a random number.
print(waiting_time)
time.sleep(waiting_time)
self.x = np.random.rand(10)
self.y = np.random.rand(10)
print(self.x)
print(self.y)
self.new_data.emit()
def run(self):
self.data_generation()
要使用該線程,可以將QMainWindow
子類化,並在其中創建RandomDataGeneration
的實例。 子類化QMainWindow
的另一個優點是,您也可以在其中移動gui設置和信號插槽連接,例如
class MyMainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.download_thread = RandomDataGeneration(self)
self.download_thread.new_data.connect(self.plot_data)
self.ui.pushButton.clicked.connect(self.start_download)
def start_download(self):
if not self.download_thread.isRunning():
self.download_thread.start()
def plot_data(self):
self.ui.MplWidget.update_plot(self.download_thread.x, self.download_thread.y)
然后主要部分變成
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
MainWindow = MyMainWindow()
MainWindow.show()
sys.exit(app.exec_())
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.