Python 在pyqt5接口中动态更新matplotlib画布

Python 在pyqt5接口中动态更新matplotlib画布,python,pyqt,pyqt5,Python,Pyqt,Pyqt5,我有一个非常简单的程序,它的结构必须保留下来,这是练习的一个条件 我们从一个按钮和画布组成的界面开始,如上图所示 单击按钮后,将启动后台任务,该任务将调用名为动画的函数。在这里,我们开始一个过程,每次都会生成随机数据。 每次有新的x和y变量时,我们都要更新绘图 代码如下: from PyQt5 import QtCore, QtWidgets from mplwidget import MplWidget import threading import time import numpy as

我有一个非常简单的程序,它的结构必须保留下来,这是练习的一个条件

我们从一个按钮和画布组成的界面开始,如上图所示

单击按钮后,将启动后台任务,该任务将调用名为动画的函数。在这里,我们开始一个过程,每次都会生成随机数据。 每次有新的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的代码


由于您正在创建一个pyqt5应用程序,我想您最好的选择是为阻塞部分使用一个QThread,并在每次生成新数据时发出一个信号。一种方法是使RandomDataGeneration成为QThread的一个子类并实现run,例如

要使用该线程,您可以将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_())

允许您更改哪些位?例如,您是否可以更改RandomDataGeneration的实现?原则上,我们可以更改RandomDataGeneration中除数据生成之外的所有内容。更新图已经是我的贡献了。
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_())