admin管理员组

文章数量:1666877

pyqtgraph嵌入pyqt5中动态更新

一、需要用到的库:

  1. PyQt5
  2. Pyqt5-tools
  3. pyqtgraph
  4. numpy
  5. sys

二、实现工具:

  1. pycharm
  2. Qt-designer

三、选择pyqtgraph的原因:

​ 之所选择pyqtgraph嵌入pyqt5,主要是因为以下原因:

  1. pyqtgraph本身就是基于python语言的一个图形库,和pyqt5的兼容性更好一些,对于我这种新手而言主要是避免了接触python之外的语言,之前也尝试过echart这个可视化效果比较好的第三方图形库,但是需要用到另外一个模块“QWebEngineView”,其中还涉及到了js语言,虽然成功的把图形嵌入到了qt里,但是卡在了数据交互的环节,花了好长时间了也没解决,最后放弃了,毕竟python渣渣实在没时间往js上面耗了。。
  2. pyqtgraph侧重于数据刷新要求较高的场景。
  3. 主要目的是为了实时显示压力传感器的变化趋势,追求实用,对可视化效果的要求没有那么高。虽然echart的视觉效果比较好,但是学渣一下弄不出来,有总比没有强(学渣最后的倔强了)等有时间了再慢慢研究echart吧。

四、整体思路:

​ 主要思路如下:

关于widget提升官方文档给出的方法<How to use pyqtgraph — pyqtgraph 0.12.3 documentation>:

  1. 在Designer,中创建一个QGraphicsView 控件 (“Display Widgets”类下的“Graphics View” ).
  2. 在QGraphicsView控件上点击右键选择“提升至”
  3. 在 “Promoted class name”栏中输入你想要变成的类名,比如“PlotWidget”类或者 “GraphicsLayoutWidget”类,这一步很重要,只有“PlotWidget”类才有plot方法
  4. 在 “Header file”下输入 “pyqtgraph”.
  5. 点击 “Add”, 然后点击 “Promote”.

五、代码

方法一:

(直接在Designer中用“提升”的方法将容纳图表的控件提升成“PlotWidget”控件,这样就可以用plot方法了)

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtCore import QTimer
from untitled import Ui_MainWindow
import pyqtgraph as pg
import numpy as np
#用于随机数的产生

class MyWindow(QMainWindow):

    def __init__(self):
        super().__init__()
        
        self.ui=Ui_MainWindow()
        #实例化主窗口

        self.ui.setupUi(self)
        #初始化主窗口

        self.DATA=np.random.normal(size=50)
		#生成50个随机数

        self.echart=self.ui.graphicsView.plot(self.DATA)
        """直接调用ui类下的PlotWidget控件的plot方法绘图,这里的“graphicsView”是PlotWidget的实例名称,在转化后的UI文件中可以看出来
        """

        self.X_ptr1 = 0
        #用于记录X轴的位置

        self.timer =QTimer()
        # 实例化一个定时器

        self.timer.timeout.connect(self.update_data)
        # 将定时器信号绑定到update_data 函数

        self.timer.start(100)
        # 启动定时器,溢出时间设定为100ms,可以理解为100ms刷新一次数据

    def update_data(self):#数据更新函数
        
        self.DATA[:-1] = self.DATA[1:]#将列表中的数左移一位

        self.DATA[-1] = np.random.normal()
        #调用随机函数生成一个随机数并且将它放在数据列表的最后一位

        self.echart.setData(self.DATA,)
        # 将更新后的数据列表放入图表中

        self.X_ptr1 += 1# 每次调用update_data函数X坐标自增1

        self.echart.setPos(self.X_ptr1,0)
        # 将更新后的X坐标也放入图表中


if __name__ == '__main__':
    app = QApplication(sys.argv)
    myWin = MyWindow()
    myWin.show()
    sys.exit(app.exec_())
方法二:

(主要利用gridLayout的addWidget方法将PlotWidget添加到gridLayout中):

import sys
from PyQt5.QtWidgets import QApplication, QMainWindow
from PyQt5.QtCore import QTimer
from untitled import Ui_MainWindow
import pyqtgraph as pg
import numpy as np
#用于随机数的产生

class MyWindow(QMainWindow):

    def __init__(self):
        super().__init__()
        #初始化父类
        
        self.ui=Ui_MainWindow()
        #实例化UI主窗口

        self.ui.setupUi(self)
        #初始化主窗口

        self.DATA=np.random.normal(size=50)
        #生成50个随机数

        self.echart=pg.PlotWidget()
        #实例化一个PlotWidget控件

        self.ui.gridLayout.addWidget(self.echart)
        #PlotWidget控件添加到gridLayout容器中

        self.my_echart=self.echart.plot(self.DATA,)
        #绘图

        self.X_ptr1 = 0
        #用于记录X轴的位置

        self.timer =QTimer()
        # 实例化一个定时器

        self.timer.timeout.connect(self.update_data)
        # 将定时器信号绑定到update_data 函数

        self.timer.start(100)
        # 启动定时器,溢出时间设定为100ms,可以理解为100ms刷新一次数据

    def update_data(self):#数据更新函数
        
        self.DATA[:-1] = self.DATA[1:]#将列表中的数左移一位

        self.DATA[-1] = np.random.normal()
        #调用随机函数生成一个随机数并且将它放在数据列表的最后一位

        self.my_echart.setData(self.DATA,)
        # 将更新后的数据列表放入图表中

        self.X_ptr1 += 1# 每次调用update_data函数X坐标自增1

        self.my_echart.setPos(self.X_ptr1,0)
        # 将更新后的X坐标也放入图表中


if __name__ == '__main__':
    app = QApplication(sys.argv)
    myWin = MyWindow()
    myWin.show()
    sys.exit(app.exec_())
转化后UI代码
# -*- coding: utf-8 -*-
# Created by: PyQt5 UI code generator 5.15.4

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(1004, 789)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        
        self.graphicsView = PlotWidget(self.centralwidget)
        self.graphicsView.setGeometry(QtCore.QRect(90, 170, 411, 281))
        self.graphicsView.setObjectName("graphicsView")
        
        self.gridLayoutWidget = QtWidgets.QWidget(self.centralwidget)
        self.gridLayoutWidget.setGeometry(QtCore.QRect(560, 170, 401, 281))
        self.gridLayoutWidget.setObjectName("gridLayoutWidget")
        
        self.gridLayout = QtWidgets.QGridLayout(self.gridLayoutWidget)
        self.gridLayout.setContentsMargins(0, 0, 0, 0)
        self.gridLayout.setObjectName("gridLayout")
        
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(220, 490, 111, 41))
        self.label.setObjectName("label")
        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setGeometry(QtCore.QRect(700, 490, 111, 41))
        self.label_2.setObjectName("label_2")
        MainWindow.setCentralWidget(self.centralwidget)
        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.label.setText(_translate("MainWindow", "方法一"))
        self.label_2.setText(_translate("MainWindow", "方法二"))
from pyqtgraph import PlotWidget
UI布局

两种方法最后实现的效果

写在最后

​ 就写到这里吧,因为本身也不是搞软件的,写的难免有所疏漏,本意只是想写个上位机直观一点监控传感器的状态,没想到嵌入图表的功能这么长时间才有所进展,老年人已经尽力了,在此记录一下这段时间的成果,写的不好的地方请多指教。

本文标签: 动态pyqtgraph