簡體   English   中英

在pyqt5界面中動態更新matplotlib canvas

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM