使用 pyqtgraph 和 PyQt5 的多个实时绘图 GUI
Multiple live plot GUI using pyqtgraph and PyQt5
我正在尝试创建一个带有多个实时绘图 EEG/ECG 图形的图形用户界面(每个绘图在不同的轴上)。
据我了解,我需要在网格布局中创建多个 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_())
我的问题是如何整合这两者,以便在每个小部件中绘制实时图表?
理想情况下,我想使用超级 class,这样我就可以简单地导入未经编辑的 gui。
我尝试将 gui.Ui_MainWindow 导入 class,然后将 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 中实现逻辑感到非常困惑。
这里有一个选项,您可以在其中使用两个 classes 并进行最小的更改。
更改 DynamicPlotter 构造函数以接受 PlotWidget 作为参数而不是创建一个新的,因为它们是在 Ui_Mainwindow 中创建并添加到布局中的。在 MainWindow class 中,为每个绘图创建一个 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_())
我正在尝试创建一个带有多个实时绘图 EEG/ECG 图形的图形用户界面(每个绘图在不同的轴上)。 据我了解,我需要在网格布局中创建多个 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_())
我的问题是如何整合这两者,以便在每个小部件中绘制实时图表? 理想情况下,我想使用超级 class,这样我就可以简单地导入未经编辑的 gui。
我尝试将 gui.Ui_MainWindow 导入 class,然后将 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 中实现逻辑感到非常困惑。
这里有一个选项,您可以在其中使用两个 classes 并进行最小的更改。
更改 DynamicPlotter 构造函数以接受 PlotWidget 作为参数而不是创建一个新的,因为它们是在 Ui_Mainwindow 中创建并添加到布局中的。在 MainWindow class 中,为每个绘图创建一个 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_())