python 多轴和动图之pyqtgraph

python 多轴和动图之pyqtgraph

2 年前 · 来自专栏 python数据分析

上篇讲了matplotlib进行多轴和动图的画图之外,这次来看看pyqtgraph如何画多轴和动图。pyqtgraph是Python中的一个库,可以和pyqt5控件来结合使用。它和matplotlib不同的是,它更倾向于绘制数据量比较大的情形,除此之外,绘制动图更新图的速度也要快些。

1、多轴

先来看看如何画多轴

import pyqtgraph as pg
app = pg.QtGui.QApplication([])
# 定义轴,想拥有几根轴就定义几个
a2 = pg.AxisItem("left")
a3 = pg.AxisItem("left")
a4 = pg.AxisItem("left")
a5 = pg.AxisItem("left")
a6 = pg.AxisItem("left")
# 视图框,用于存放折线
v2 = pg.ViewBox()
v3 = pg.ViewBox()
v4 = pg.ViewBox()
v5 = pg.ViewBox()
v6 = pg.ViewBox()
# 创建视图
pw = pg.GraphicsView()
pw.setWindowTitle('pyqtgraph 标题')
pw.show()
# 创建图形布局
l = pg.GraphicsLayout()
# 设置视图中心小部件 为该布局
pw.setCentralWidget(l)
# 向布局添加轴
# 注意这里col参数的位置,col的值大小表示轴的排列位置
l.addItem(a2, row = 2, col = 5,  rowspan=1, colspan=1)
l.addItem(a3, row = 2, col = 4,  rowspan=1, colspan=1)
l.addItem(a4, row = 2, col = 2,  rowspan=1, colspan=1)
l.addItem(a5, row = 2, col = 3,  rowspan=1, colspan=1)
l.addItem(a6, row = 2, col = 1,  rowspan=1, colspan=1)
#l.addItem(a6, row = 2, col = 3,  rowspan=1, colspan=1)
# 至少有一个绘图项使用它自己的视图框和左轴。
pI = pg.PlotItem()  # 定义一个绘图项
v1 = pI.vb # 对绘图项的视图框的引用
l.addItem(pI, row = 2, col = 6,  rowspan=1, colspan=1) # 添加绘图框到图形布局
# 向绘图框添加视图框
l.scene().addItem(v2)
l.scene().addItem(v3)
l.scene().addItem(v4)
l.scene().addItem(v5)
l.scene().addItem(v6)
# 用轴连接 存放折线的视图框
a2.linkToView(v2)
a3.linkToView(v3)
a4.linkToView(v4)
a5.linkToView(v5)
a6.linkToView(v6)
# 链接视图框,绘图项的视图框上,整体缩放所有的折线
v2.setXLink(v1)
v3.setXLink(v2)
v4.setXLink(v3)
v5.setXLink(v4)
v6.setXLink(v5)
# 轴标签
pI.getAxis("left").setLabel('axis 1 in ViewBox of PlotItem', color='#FFFFFF')
a2.setLabel('axis 2 in Viewbox 2', color='#2E2EFE')
a3.setLabel('axis 3 in Viewbox 3', color='#2EFEF7')
a4.setLabel('axis 4 in Viewbox 4', color='#2EFE2E')
a5.setLabel('axis 5 in Viewbox 5', color='#FFFF00')
a6.setLabel('axis 6 in Viewbox 6', color='#FE2E64')
# slot: 插槽:调整大小时更新视图
def updateViews():
    # setGeometry设置几何图形
    # sceneBoundingRect场景边界矩形
    v2.setGeometry(v1.sceneBoundingRect())
    v3.setGeometry(v1.sceneBoundingRect())
    v4.setGeometry(v1.sceneBoundingRect())
    v5.setGeometry(v1.sceneBoundingRect())
    v6.setGeometry(v1.sceneBoundingRect())
# 折线点值 (轴刻度范围自动按最大最小值生成)
x = [1,2,3,4,5,6]
y1 = [0,4,6,8,10,4]
y2 = [0,5,7,9,11,3]
y3 = [0,1,2,3,4,12]
y4 = [0,8,0.3,0.4,2,5]
y5 = [0,1,6,4,2,1]
y6 = [0,0.2,0.3,0.4,0.5,0.6]
# 给绘图项的视图框添加折线xy点的值,折线颜色
v1.addItem(pg.PlotCurveItem(x, y1, pen='#FFFFFF'))
v2.addItem(pg.PlotCurveItem(x, y2, pen='#2E2EFE'))
v3.addItem(pg.PlotCurveItem(x, y3, pen='#2EFEF7'))
v4.addItem(pg.PlotCurveItem(x, y4, pen='#2EFE2E'))
v5.addItem(pg.PlotCurveItem(x, y5, pen='#FFFF00'))
v6.addItem(pg.PlotCurveItem(x, y6, pen='#FE2E64'))
#  调整大小时更新
v1.sigResized.connect(updateViews)
# 开始时自动调整一次以适应视图
# enableAutoRange 启用自动范围
v2.enableAutoRange(axis= pg.ViewBox.XYAxes, enable=True)
v3.enableAutoRange(axis= pg.ViewBox.XYAxes, enable=True)
v4.enableAutoRange(axis= pg.ViewBox.XYAxes, enable=True)
v5.enableAutoRange(axis= pg.ViewBox.XYAxes, enable=True)
v6.enableAutoRange(axis= pg.ViewBox.XYAxes, enable=True)
updateViews()
app.exec_()

最终效果

2、动图

import pyqtgraph as pg
import numpy as np
import array
app = pg.mkQApp()#建立app
win = pg.GraphicsWindow()#建立窗口
win.setWindowTitle(u'pyqtgraph逐点画波形图')
win.resize(800, 500)#小窗口大小
data =[] #可动态改变数组的大小,double型数组
historyLength = 100#横坐标长度
p = win.addPlot()#把图p加入到窗口中
idx = 0
p.showGrid(x=True, y=True)#把X和Y的表格打开
p.setLabel(axis='left', text='y / V')#靠左
p.setLabel(axis='bottom', text='x / point')
p.setTitle('y = sin(x)')#表格的名字
curve = p.plot()#绘制一个图形
def plotData():
    global idx#内部作用域想改变外部域变量
    global B
    tmp = np.sin(np.pi / 50 * idx)
    if len(data)<historyLength:
    #print(len(data))
        data.append(tmp)
    #print(B)
        p.setRange(xRange=[0, historyLength+0], yRange=[-1.2, 1.2], update=False)
        #print(data)
    else:
        data.append(tmp)
        B=B+1
        # print(B)
        p.setRange(xRange=[B, historyLength+B], yRange=[-1.2, 1.2], update=False)
        #data[:-1] = data[1:]#前移
        #data[-1] = tmp
        if B>100:
            timer.stop()
    curve.setData(data)
    idx += 1
timer = pg.QtCore.QTimer()
timer.timeout.connect(plotData)#定时调用plotData函数
timer.start(50)#多少ms调用一次
app.exec_()

最终效果

3、多轴和动图

如何画一张图,既是多轴又是动图呢

import pyqtgraph as pg
import numpy as np
app = pg.QtGui.QApplication([])
# 定义轴
a2 = pg.AxisItem("left")
a3 = pg.AxisItem("left")
a4 = pg.AxisItem("left")
a5 = pg.AxisItem("left")
a6 = pg.AxisItem("left")
# 视图框,用于存放折线
v2 = pg.ViewBox()
v3 = pg.ViewBox()
v4 = pg.ViewBox()
v5 = pg.ViewBox()
v6 = pg.ViewBox()
# 创建视图
pw = pg.PlotWidget()
pw.setWindowTitle('pyqtgraph 标题')
pw.show()
# 创建图形布局
l = pg.GraphicsLayout()
# 设置视图中心小部件 为该布局
pw.setCentralWidget(l)
# 向布局添加轴
# 注意这里col参数的位置
l.addItem(a2, row = 2, col = 5,  rowspan=1, colspan=1)
l.addItem(a3, row = 2, col = 4,  rowspan=1, colspan=1)
l.addItem(a4, row = 2, col = 3,  rowspan=1, colspan=1)
l.addItem(a5, row = 2, col = 2,  rowspan=1, colspan=1)
l.addItem(a6, row = 2, col = 1,  rowspan=1, colspan=1)
#l.addItem(a6, row = 2, col = 3,  rowspan=1, colspan=1)
# 至少有一个绘图项使用它自己的视图框和左轴。
pI = pg.PlotItem()  # 定义一个绘图项
v1 = pI.vb # 对绘图项的视图框的引用
l.addItem(pI, row = 2, col = 6,  rowspan=1, colspan=1) # 添加绘图框到图形布局
# 向绘图框添加视图框
l.scene().addItem(v2)
l.scene().addItem(v3)
l.scene().addItem(v4)
l.scene().addItem(v5)
l.scene().addItem(v6)
# 用轴连接 存放折线的视图框
a2.linkToView(v2)
a3.linkToView(v3)
a4.linkToView(v4)
a5.linkToView(v5)
a6.linkToView(v6)
# 链接视图框,我也不知道干嘛这样写,但是写上就会在--绘图项的视图框上,整体缩放所有的折线
v2.setXLink(v1)
v3.setXLink(v2)
v4.setXLink(v3)
v5.setXLink(v4)
v6.setXLink(v5)
# 轴标签
pI.getAxis("left").setLabel('axis 1 in ViewBox of PlotItem', color='#FFFFFF')
a2.setLabel('axis 2 in Viewbox 2', color='#2E2EFE')
a3.setLabel('axis 3 in Viewbox 3', color='#2EFEF7')
a4.setLabel('axis 4 in Viewbox 4', color='#2EFE2E')
a5.setLabel('axis 5 in Viewbox 5', color='#FFFF00')
a6.setLabel('axis 6 in Viewbox 6', color='#FE2E64')
historyLength = 100#横坐标长度
#p = win.addPlot()#把图p加入到窗口中
pI.showGrid(x=True, y=True)#把X和Y的表格打开
pI.setLabel(axis='bottom', text='x / point')
# slot: 插槽:调整大小时更新视图
def updateViews():
    # setGeometry设置几何图形
    # sceneBoundingRect场景边界矩形
    v2.setGeometry(v1.sceneBoundingRect())
    v3.setGeometry(v1.sceneBoundingRect())
    v4.setGeometry(v1.sceneBoundingRect())
    v5.setGeometry(v1.sceneBoundingRect())
    v6.setGeometry(v1.sceneBoundingRect())
# 折线点值 (轴刻度范围自动按最大最小值生成)
x = []
y1 = []
y2 = []
y3 = []
y4 = []
y5 = []
y6 = []
def plotdata():
    global i
    global B
    tmp = np.sin(np.pi / 50 * i)
    x.append(i)
    y1.append(tmp)
    y2.append(1.5 * tmp)
    y3.append(2 * tmp)
    y4.append(2.5 * tmp)
    y5.append(tmp * 3)
    y6.append(tmp * 3.5)
    # pI.setRange(xRange=[0, historyLength + 0], yRange=[-5, 20], update=True)
# 给绘图项的视图框添加折线xy点的值,折线颜色
    v1.addItem(pg.PlotCurveItem(x, y1, pen='#FFFFFF'))
    v2.addItem(pg.PlotCurveItem(x, y2, pen='#2E2EFE'))
    v3.addItem(pg.PlotCurveItem(x, y3, pen='#2EFEF7'))
    v4.addItem(pg.PlotCurveItem(x, y4, pen='#2EFE2E'))
    v5.addItem(pg.PlotCurveItem(x, y5, pen='#FFFF00'))
    v6.addItem(pg.PlotCurveItem(x, y6, pen='#FE2E64'))
    if len(x) >=historyLength:
        B = B + 1
    else:
        B = 0
        # print(B)
    pI.setRange(xRange=[B, historyLength + B], yRange=[-15, 20], update=True)
    i=i+1
#  调整大小时更新
v1.sigResized.connect(updateViews)
# 开始时自动调整一次以适应视图
# enableAutoRange 启用自动范围
v2.enableAutoRange(axis= pg.ViewBox.XYAxes, enable=True)
v3.enableAutoRange(axis= pg.ViewBox.XYAxes, enable=True)
v4.enableAutoRange(axis= pg.ViewBox.XYAxes, enable=True)
v5.enableAutoRange(axis= pg.ViewBox.XYAxes, enable=True)
v6.enableAutoRange(axis= pg.ViewBox.XYAxes, enable=True)
timer = pg.QtCore.QTimer()