【问题标题】:Multiple live plot GUI using pyqtgraph and PyQt5使用 pyqtgraph 和 PyQt5 的多个实时绘图 GUI
【发布时间】:2021-12-27 18:30:25
【问题描述】:

我正在尝试使用多个实时绘图 EEG/ECG 图(每个绘图在不同的轴上)创建一个 gui。 据我了解,我需要在网格布局中创建多个 PlotWidgets。

我使用 pyqtgraph 创建了一个实时绘图,但我不确定如何将其合并到 GUI 中:

从 pyqtgraph.Qt 导入 QtGui、QtCore 将 pyqtgraph 导入为 pg 导入集合 随机导入 进口时间 导入数学 将 numpy 导入为 np

class DynamicPlotter:

    def __init__(self, sampleinterval=0.1, timewindow=10., size=(600, 350)):
        # Data stuff
        self.interval = int(sampleinterval * 1000)
        self.bufsize = int(timewindow / sampleinterval)
        self.databuffer = collections.deque([0.0] * self.bufsize, self.bufsize)
        self.x = np.linspace(-timewindow, 0.0, self.bufsize)
        self.y = np.zeros(self.bufsize, dtype=float)
        # PyQtGraph stuff
        self.app = QtGui.QApplication([])
        self.plt = pg.plot(title='EEG/ECG Live Plot')
        self.plt.resize(*size)
        self.plt.showGrid(x=True, y=True)
        #self.plt.setXRange(5,20, padding=0)
        self.plt.setLabel('left', 'Amplitude', 'uVrms')
        self.plt.setLabel('bottom', 'Time', 's')
        self.curve = self.plt.plot(self.x, self.y, pen=(255, 0, 0))

        # QTimer
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.updateplot)
        self.timer.start(self.interval)

    def getdata(self):
        frequency = 0.5
        noise = random.normalvariate(0., 1.)
        new = 10. * math.sin(time.time() * frequency * 2 * math.pi) + noise
        return new

    def updateplot(self):
        self.databuffer.append(self.getdata())
        self.y[:] = self.databuffer
        self.curve.setData(self.x, self.y)
        self.app.processEvents()

    def run(self):
        self.app.exec_()

if __name__ == '__main__':
    livePlot = DynamicPlotter(sampleinterval=0.05, timewindow=5.)
    livePlot.run()

这是基本的 GUI(网格内有 3 个绘图小部件,主窗口中有一些标签):

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(845, 727)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.labelTitle = QtWidgets.QLabel(self.centralwidget)
        self.labelTitle.setGeometry(QtCore.QRect(280, 0, 291, 51))
        font = QtGui.QFont()
        font.setPointSize(12)
        font.setBold(True)
        font.setWeight(75)
        self.labelTitle.setFont(font)
        self.labelTitle.setObjectName("labelTitle")
        self.labelCh1 = QtWidgets.QLabel(self.centralwidget)
        self.labelCh1.setGeometry(QtCore.QRect(20, 90, 31, 51))
        self.labelCh1.setObjectName("labelCh1")
        self.labelCh2 = QtWidgets.QLabel(self.centralwidget)
        self.labelCh2.setGeometry(QtCore.QRect(20, 180, 31, 51))
        self.labelCh2.setObjectName("labelCh2")
        self.labelCh3 = QtWidgets.QLabel(self.centralwidget)
        self.labelCh3.setGeometry(QtCore.QRect(20, 260, 31, 51))
        self.labelCh3.setObjectName("labelCh3")
        self.widget = QtWidgets.QWidget(self.centralwidget)
        self.widget.setGeometry(QtCore.QRect(70, 70, 741, 261))
        self.widget.setObjectName("widget")
        self.gridLayout = QtWidgets.QGridLayout(self.widget)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setObjectName("gridLayout")
        self.ch1PlotWidget = PlotWidget(self.widget)
        self.ch1PlotWidget.setObjectName("ch1PlotWidget")
        self.gridLayout.addWidget(self.ch1PlotWidget, 0, 0, 1, 1)
        self.ch2PlotWidget = PlotWidget(self.widget)
        self.ch2PlotWidget.setObjectName("ch2PlotWidget")
        self.gridLayout.addWidget(self.ch2PlotWidget, 1, 0, 1, 1)
        self.ch3PlotWidget = PlotWidget(self.widget)
        self.ch3PlotWidget.setObjectName("ch3PlotWidget")
        self.gridLayout.addWidget(self.ch3PlotWidget, 2, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 845, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.labelTitle.setText(_translate("MainWindow", "EEG/ECG Recording GUI"))
        self.labelCh1.setText(_translate("MainWindow", "Ch 1"))
        self.labelCh2.setText(_translate("MainWindow", "Ch 2"))
        self.labelCh3.setText(_translate("MainWindow", "Ch 3"))
from pyqtgraph import PlotWidget


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

我的问题是如何整合这两者,以便在每个小部件中绘制实时图表? 理想情况下,我想使用一个超类,这样我就可以简单地导入未经编辑的 gui。

我尝试将 gui.Ui_MainWindow 导入到类中,然后将 self.plt 覆盖为 self.Ch1PlotWidget

from pyqtgraph.Qt import QtGui, QtCore, QtWidgets
import gui as gui
import sys
import pyqtgraph as pg
import collections
import random
import time
import math
import numpy as np


class MainWindow(QtWidgets.QMainWindow, gui.Ui_MainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent=parent)
        self.setupUi(self)

        # Data stuff
        self.interval = 100
        self.bufsize = int(10 / self.interval)
        self.databuffer = collections.deque([0.0] * self.bufsize, self.bufsize)
        self.x = np.linspace(-10, 0.0, self.bufsize)
        self.y = np.zeros(self.bufsize, dtype=float)
        # PyQtGraph stuff
        self.app = QtGui.QApplication([])
        self.ch1PlotWidget = pg.plot(title='Live Plot')
        self.ch1PlotWidget.resize(600, 350)
        self.ch1PlotWidget.showGrid(x=True, y=True)
        # self.plt.setXRange(5,20, padding=0)
        self.ch1PlotWidget.setLabel('left', 'Amplitude', 'uVrms')
        self.ch1PlotWidget.setLabel('bottom', 'Time', 's')
        self.curve = self.ch1PlotWidget.plot(self.x, self.y, pen=(255, 0, 0))

        # QTimer
        self.timer = QtCore.QTimer()
        self.timer.timeout.connect(self.updateplot)
        self.timer.start(self.interval)

    def getdata(self):
        frequency = 0.5
        noise = random.normalvariate(0., 1.)
        new = 10. * math.sin(time.time() * frequency * 2 * math.pi) + noise
        return new

    def updateplot(self):
        self.databuffer.append(self.getdata())
        self.y[:] = self.databuffer
        self.curve.setData(self.x, self.y)
        self.app.processEvents()


if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())

对不起所有的代码,我只是对如何在 gui 中实现逻辑感到很困惑。

【问题讨论】:

    标签: python pyqt pyqt5 pyqtgraph


    【解决方案1】:

    这是一个选项,您可以在其中使用这两个类,只需进行最少的更改。

    更改 DynamicPlotter 构造函数以接受 PlotWidget 作为参数而不是创建新的,因为它们是在 Ui_Mainwindow 中创建并添加到布局中的。在 MainWindow 类中,为每个绘图创建一个 DynamicPlotter 对象(并保持一个持久引用,在本例中我将它们添加到列表 self.plots)。

    class DynamicPlotter:
    
        def __init__(self, plot, sampleinterval=0.1, timewindow=10., size=(600, 350)):
            # Data stuff
            self.interval = int(sampleinterval * 1000)
            self.bufsize = int(timewindow / sampleinterval)
            self.databuffer = collections.deque([0.0] * self.bufsize, self.bufsize)
            self.x = np.linspace(-timewindow, 0.0, self.bufsize)
            self.y = np.zeros(self.bufsize, dtype=float)
            
            # PyQtGraph stuff
            self.plt = plot
            self.plt.setTitle('EEG/ECG Live Plot')
            self.plt.resize(*size)
            self.plt.showGrid(x=True, y=True)
            #self.plt.setXRange(5,20, padding=0)
            self.plt.setLabel('left', 'Amplitude', 'uVrms')
            self.plt.setLabel('bottom', 'Time', 's')
            self.curve = self.plt.plot(self.x, self.y, pen=(255, 0, 0))
    
            # QTimer
            self.timer = QtCore.QTimer()
            self.timer.timeout.connect(self.updateplot)
            self.timer.start(self.interval)
    
        def getdata(self):
            frequency = 0.5
            noise = random.normalvariate(0., 1.)
            new = 10. * math.sin(time.time() * frequency * 2 * math.pi) + noise
            return new
    
        def updateplot(self):
            self.databuffer.append(self.getdata())
            self.y[:] = self.databuffer
            self.curve.setData(self.x, self.y)
    
    
    class MainWindow(QtWidgets.QMainWindow, gui.Ui_MainWindow):
        def __init__(self, parent=None):
            super(MainWindow, self).__init__(parent=parent)
            self.setupUi(self)
            self.plots = []
            for plot in (self.ch1PlotWidget, self.ch2PlotWidget, self.ch3PlotWidget):
                self.plots.append(
                    DynamicPlotter(plot, sampleinterval=0.05, timewindow=5.)
                    )
    
    
    if __name__ == "__main__":
        app = QtGui.QApplication(sys.argv)
        w = MainWindow()
        w.show()
        sys.exit(app.exec_())
    
    

    【讨论】:

    • 非常感谢,亚历克!这是一个非常简洁的解决方案,不需要对 gui.UI_Mainwindow 进行任何更改。
    猜你喜欢
    • 2018-03-05
    • 2019-04-16
    • 2019-04-01
    • 2017-12-16
    • 2019-02-02
    • 2019-07-24
    • 2018-09-12
    • 2023-04-06
    • 2018-04-13
    相关资源
    最近更新 更多