百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

使用PyQtGraph 自定义绘图

myzbx 2025-02-06 15:47 29 浏览

Python 的主要优势之一是探索性数据科学和可视化生态体系。一般的工具链为Pandas、numpy、sklearn 进行数据分析和使用matplotlib进行绘图。

但是如果需要自己自定义一个个性化的图形界面工具,则可能不是很合适。为了实现这种需求,可以使用PyQt构建GUI应用程序,但是可以使用上面的生态系工具构建自定义的复杂的数据驱动应用程序和交互式仪表板。

对于简单且高度交互的绘图,本文介绍一个Python GUI的绘图PyQtGraph。

概述

PyQtGraph建立在Qt QGraphicsScene的原生库,可提供更好更高性能绘图能力,特别是对于实时数据,可以提供交互性和使用Qt图形小部件轻松自定义绘图的能力。

PyQtGraphzh主要特点有:

各种线图和散点图;

数据平移/缩放鼠标;

实时数据更新和显示,交互数据的快速绘制;

图像显示与互动的查找表和水平控制;

支持完全的类型(常见类型和Qt类型,比如RGB,RGBA,或亮度,QColor)

2D交互视图绘制;

交互式视窗旋转/缩放鼠标;

视频流的显示和实时交互;

网格的等值面渲染;

三维图形系统;

三维表面图和散点图;

实验数据切片的多维图像任意角度的函数(比如,对MRI数据处理);

更容易编程的基本的3D场景图;

对感兴趣的控制区选择和数据显示;

交互标记垂直/水平的地块的位置和区域;

从图像中选择任意区域的部件和自动切片数据匹配;

安装

为了使用PyQtGraph做图,必须先安装该模块。PyQtGraph依赖Pyhon 3.7和PyQt,所以需要先安装这些库。

在Pyhon 3.7环境下,可以用:

pip install qt
pip install pyqt

然后

pip install pyqtgraph

为了方便可以使用anaconda环境,这样只需安装

conda install qt
conda install pyqt

然后

conda install pyqtgraph

PyQtGraph小部件

在PyQtGraph中,所有图都是使用PlotWidget小部件。小部件提供了canvas,可以在其上添加和配置任何类型的绘图。在hood下,绘图小部件使用本机Qt QGraphicsScene。例如,我们创建一个PlotWidget至于任何其他小部件的例子:


from PyQt6 import QtWidgets
from pyqtgraph import PlotWidget, plot
import pyqtgraph as pg
import sys
import os
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.graphWidget = pg.PlotWidget()
self.setCentralWidget(self.graphWidget)
x = [1, 2, 3, 4, 5, 6, 7, 8]
y = [3567.44,3462.95,3309.75,3167.13,3508.70,3284.83,3313.58,3268.02]
self.graphWidget.plot(x, y)
def main():
app = QtWidgets.QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec())
if __name__ == '__main__':
main()

PyQtGraph 的默认绘图样式非常简单——黑色背景和细(几乎不可见)白线。在下一节中,我们将看看 PyQtGraph 中有哪些可用选项来改善绘图的外观和可用性。

造型图

PyQtGraph继承了Qt的QGraphicsScene渲染图表,可以实现使用所有标准Qt线条和形状样式选项。PyQtGraph提供了一个API用于使用这些来绘制绘图和管理绘图画布。

下面我们将介绍创建和自定义绘图所需的最常见的样式功能。

背景色

可以通过调用.setBackground来改变背景颜色。PlotWidget实例(在 self.graphWidget)。下面的代码将通过传入字符串“w”将背景设置为白色。

self.graphWidget.setBackground('w')

可以随时设置(和更新)绘图的背景颜色。

from PyQt5 import QtWidgets
from pyqtgraph import PlotWidget, plot
import pyqtgraph as pg
import sys
import os
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.graphWidget = pg.PlotWidget()
self.setCentralWidget(self.graphWidget)
x = [1, 2, 3, 4, 5, 6, 7, 8]
y = [3567.44,3462.95,3309.75,3167.13,3508.70,3284.83,3313.58,3268.02]
self.graphWidget.setTitle("Chongchong", color="b", size="30pt")
self.graphWidget.plot(x, y)
def main():
app = QtWidgets.QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec())
if __name__ == '__main__':
main()

有许多使用单个字母的简单颜色表示,这是基于matplotlib. 主意这种表示中表示黑色的是“k”。

除了这些单字母代码之外,还可以使用十六进制的RGB和RGBA 设置更复杂的颜色,

比如 #672922

self.graphWidget.setBackground('#bbccaa')

RGB和RGBA值可以分别作为3元组或4元组传入,使用值 0-255。

self.graphWidget.setBackground((100,50,255)) # RGB each 0-255
self.graphWidget.setBackground((100,50,255,25))

最后,还可以使用Qt的颜色表示法QColor:

from PyQt5 import QtGui
self.graphWidget.setBackground(QtGui.QColor(100,50,254,25))

如果使用特定的QColor应用程序中其他位置的对象,或将绘图背景设置为默认的GUI背景颜色。

color = self.palette().color(QtGui.QPalette.Window)
self.graphWidget.setBackground(color)

线条颜色、宽度和样式

PyQtGraph中的线条也是使用标准Qt绘制的 QPen类型,可以像在任何其他操作中一样完全控制线条绘制QGraphicsScene绘画。要使用笔绘制一条线,只需创建一个新的QPen实例并将其传递给 plot方法。

下面的代码创建一个QPen对象,传入一个3元组int指定 GB值(全红色)的值。也可以通过传递 'r' 或 Qcolor。然后通过pen参数将其它传入plot。

pen = pg.mkPen(color=(255, 0, 0))
self.graphWidget.plot(hour, temperature, pen=pen)


效果如下:

线条颜色

通过改变QPen可以改变线条的外观,包括以像素为单位的线条宽度和使用标准Qt线条样式的样式(虚线、点线等)。比如创建一条15像素宽的红色虚线,代码为:

pen = pg.mkPen(color=(255, 0, 0), width=15, style=QtCore.Qt.DashLine)

结果如下:

标准Qt线条样式都可以使用,包括Qt.SolidLine, Qt.DashLine, Qt.DotLine, Qt.DashDotLine和 Qt.DashDotDotLine,起对样样式官方图如下

线标记

对于许多绘图,在绘图上添加标记或代替线条放置标记可能会有所帮助。要在绘图上绘制标记,请在调用时传递符号以用作标记.plot。

self.graphWidget.plot(hour, temperature, symbol='+')

此外symbol你也可以传入symbolSize,symbolBrush和 ymbolPen参数。传递的值作为 symbolBrush可以是任何颜色或QBrush样式,symbolPen中可以中使用颜色参数或QPen实例。

画笔

画用于绘制形状的轮廓,用于填充。

下面的代码将在粗红线上给出一个大小为30的蓝色十字标记。

pen = pg.mkPen(color=(255, 0, 0), width=15, style=QtCore.Qt.DashLine)
self.graphWidget.plot(hour, temperature, pen=pen, symbol='+', symbolSize=30, symbolBrush=('b'))

也支持传入任何 QPainterPath对象,然后完全自定义的标记形状。

画板标题

画板标题对于为给定图表上显示的内容提供上下文非常重要。在 PyQtGraph中,可以使用 PlotWidget对象的setTitle()方法,设定标题字符串。

self.graphWidget.setTitle("Chongchong")

可以通过传递其他参数将文本样式(包括颜色、字体大小和粗细)应用于标题(以及 PyQtGraph中的任何其他标签)。

比如设置标题蓝色,字体大小为 30px。

self.graphWidget.setTitle("Chongchong", color="b", size="30pt")

也支持使用HTML标记语法来设置标题的样式,比如:

self.graphWidget.setTitle("Chongchong")

轴标识

与标题类似,可以使用setLabel()方法来创建我们的轴标识。这需要两个参数, position和text。position参数可以设置'left,'right','top','bottom'的值,用来支指出放置文本的轴的位置。参数text是要显示标题的文本。

可以将其他样式参数传递给该方法。但与标题略有不同,必须是有效的CSS名称-值对。例如,大小为font-size. 因为名字font-size有连字符,不能直接作为参数传递,必须使用 **dictionary方法。

styles = {'color':'r', 'font-size':'20px'}
self.graphWidget.setLabel('left', '上证指数', **styles)
self.graphWidget.setLabel('bottom', '月', **styles)

也支持HTML样式的语法,比如

self.graphWidget.setLabel('left', "上证指数")
self.graphWidget.setLabel('bottom', "")


图例

除了轴和绘图标题之外,通常会要显示一个图例来标识给定线所代表的内容。比如添加了多条线时,可以通过调用来为绘图添加图例。可以通过PlotWidget对象的.addLegent。但是需要在调用时为每一行提供一个名称 .plot()。比如,以下代码在绘制的线分配了一个名称“2022年” .plot(). 此名称将用于标识图例中的行。

self.graphWidget.plot(x, y, name = "2022年", pen = pen, symbol='+', symbolSize=30, symbolBrush=('b'))
self.graphWidget.addLegend()

图例默认显示在左上角。可以通过将2元组传递给offset创建图例时的参数。

背景网格

添加背景网格可以让绘图更易于阅读,尤其是在尝试将相对x和y值相互比较时。可以通过调用PlotWidget的.showGrid为打开背景网格,可以独立切换x和y网格。

self.graphWidget.showGrid(x=True, y=True)

设置轴限制

有时候会有限制绘图上可见的数据范围或将轴锁定在一致的范围内。在 PyQtGraph 中,这可以使用.setXRange()和.setYRange()方法来强制绘图仅显示轴上指定范围内的数据。

self.graphWidget.setXRange(2, 5, padding=0)
self.graphWidget.setYRange(3300, 3500, padding=0)

一个可选的填充参数导致范围设置为大于指定的分数(默认情况下在0.02和0.1之间,取决于ViewBox的大小)。如果要完全删除此填充,请传递0。

绘制多条线

一个图中绘制多条线是很常见的。在PyQtGraph中,只需在PlotWidget中多次调用.plot()即可. 下面的例子,我绘制两条相似的数据线,每条线使用相同的线型、粗细等,但改变线的颜色。为了方便,定义一个plot函数,接受x和y要绘制的参数、线的名称(用于图例)和颜色。将颜色用于线条和标记颜色。

def plot(self, x, y, plotname, color):
pen = pg.mkPen(color=color)
self.graphWidget.plot(x, y, name=plotname, pen=pen, symbol='+', symbolSize=30, symbolBrush=(color))
self.plot(x, y1, "2021", 'r')
self.plot(x, y, "2022", 'b')

其结果如下图:


清除画板

有事可能希望定期清除和刷新绘图可以通过.clear()调用来实现。

self.graphWidget.clear()

将会从图中删除线条,但保持所有其他属性相同。

更新画板

虽然简单地清除画板并重新绘制所有元素,这样一来Qt必须销毁并重新创建 QGraphicsScene对象和所有元素。对于小型或简单的绘图,这没什么问题,但对一个比较复杂耗时的图,可能更好的方法是跟新局部数据,而不是从头来一遍。PyQtGraph 获取新数据并更新绘制的线,而不会影响画板的其他部分。

要更新画线,需要对线条对象的引用。首次使用创建行时返回此引用.plot可以简单地将它存储在一个变量中。请注意,这是对线不是对画板的引用。

my_line_ref = graphWidget.plot(x, y)

有了引用变量,只需其.setData关更新数据。

from PyQt5 import QtWidgets, QtCore
from pyqtgraph import PlotWidget, plot
import pyqtgraph as pg
import sys
import os
from random import randint
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.graphWidget = pg.PlotWidget()
self.setCentralWidget(self.graphWidget)
self.x = list(range(100))
self.y = [randint(0,100) for _ in range(100)]
self.graphWidget.setBackground('w')
pen = pg.mkPen(color=(255, 0, 0))
self.data_line = self.graphWidget.plot(self.x, self.y, pen=pen)
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.show()
sys.exit(app.exec())

每50毫秒更新一次数据,尽管 PyQtGraph 绘制数据的速度比这快得多,但很难观察!为此,可以定义了一个Qt计时器,并将其设置为调用自定义方法update_plot_data更改数据,这样就会生成滚动的动态图:

self.timer = QtCore.QTimer()
self.timer.setInterval(50)
self.timer.timeout.connect(self.update_plot_data)
self.timer.start()
def update_plot_data(self):
self.x = self.x[1:]
self.x.append(self.x[-1] + 1)
self.y = self.y[1:]
self.y.append( randint(0,100))
self.data_line.setData(self.x, self.y)

总结

本文我们介绍了,使用PyQtGraph绘制简单的图并自定义线条、标记和标签。实际上PyQtGraph是一个强大的绘图工具,作为一个入门介绍,想更深入一步的研究和使用可以参考PyQtGraph官方更详细的文档和实例程序。

相关推荐

JMeter:执行顺序与作用域(jmeter顺序执行怎么设置)

一、执行顺序类似于运算符或操作符的优先级,当JMeter测试中包含多个不同的元素时,哪些元素先执行,哪些元素后执行,并不是严格按照它们出现的先后顺序依次有序执行的,而是会遵循一定的内部规则,我们称之为...

彻底搞懂C语言指针(c语言 指针用法)

指针是C语言的难点,本篇文章总结一下各类指针的用法。指针是个变量,它存储的是变量的地址,这个地址指向哪里,取决于指针的类型,指针类型包括以下几种:基本类型指针数组类型指针函数类型指针结构体类型指针联合...

Excel运算符相关知识点分享(excel运算符有哪些类型)

在Excel中,运算符主要用于执行各种计算和逻辑操作主要分为以下四类1.比较运算符在Excel中,比较运算符用于比较两个值,并返回逻辑结果TRUE(真)或FALSE(假)。它们常用于条件判...

Python编程基础:运算符的优先级(python运算符优先级记忆口诀)

多个运算符同时出现在一个表达式中时,先执行哪个,后执行哪个,这就涉及运算符的优先级。如数学表达式,有+、-、×、÷、()等,优先级顺序是()、×、÷、+、-,如5+(5-3)×4÷2,先计算(5-3)...

吊打面试官(四)--Java语法基础运算符一文全掌握

简介本文介绍了Java运算符相关知识,包含运算规则,运算符使用经验,特殊运算符注意事项等,全文5400字。熟悉了这些内容,在运算符这块就可以吊打面试官了。Java运算符的规则与特性1.贪心规则(Ma...

C语言零基础教学-3-运算符与表达式

同学们好,今天学习c元基础知识第三讲:运算符与表达式。本节内容将学习算数运算符与算数表达式。·至臻至减运算符、赋值运算符、逗号运算符、求至结运算符。→首先学习算数运算符,它包含加减乘除求余数正负。比如...

Python运算符优先级终极指南:避免表达式计算的陷阱

混合表达式中的运算符优先级当Python表达式中同时出现算术运算符、布尔运算符和比较运算符时,计算顺序由运算符优先级决定:算术运算符(最高优先级)包括:乘方(**)、乘除(*,/,//,%)、加...

Python自动化办公应用学习笔记12——运算符及运算符优先级

一、运算符1.算术运算符:运算符名称描述示例+加数值相加10+3=13-减数值相减10-3=7*乘数值相乘10*3=30/除浮点数除法10/3≈3.33//整除向下...

python3-运算符优先级(python运算符优先级最高)

#挑战30天在头条写日记#Python运算符优先级以下列出了从最高到最低优先级的所有运算符,相同单元格内的运算符具有相同优先级。运算符均指二元运算,除非特别指出。相同单元格内的运算符从左至右分组...

Java运算符优先级表(java语言中运算符的优先级)

Java语言中有很多运算符,由于运算符优先级的问题经常会导致程序出现意想不到的结果,为了避免程序可能由于运算顺序而导致一系列的问题,Java初学者需应尽可能掌握这些运算符规律图示给大家详细介绍了运算符...

Excel公式中运算符类型及优先顺序

在Excel中公式中,用到的一些运算符是有优先计算顺序的,详见下图。下面我们简单介绍一下这些运算符的使用方法。说明:Excel中所有公式及运算符,都需要在英文输入法半角状态输入,不要输入中文字符或者全...

JavaScript基础知识14——运算符:逻辑运算符,运算符优先级

哈喽,大家好,我是雷工!一、逻辑运算符1、概念:在程序中用来连接多个比较条件时候使用的符号。2、应用场景:在程序中用来连接多个比较条件时候使用。3、逻辑运算符符号:4、代码演示逻辑运算符的使用:逻辑...

认识Excel中的运算符(excel中的运算符包括在哪里)

Excel中,函数与公式无疑是最具有魅力的功能之一。使用函数与公式,能帮助用户完成多种要求的数据运算、汇总、提取等工作。函数与公式同数据验证功能相结合,能限制数据的输入内容或类型,还可以制作动态更新...

JavaScript 中的运算符优先级(javascript中的运算符分为哪几种?)

#寻找热爱表达的你#新人求关注,点击右上角↗关注,博主日更,全年无休,您的关注是我的最大的更新的动力~感谢大家了运算符优先级在JavaScript中是指决定表达式中不同操作符执行顺序的规...

从几个细节问题出发,如何写好产品需求文档?

来人人都是产品经理【起点学院】,BAT实战派产品总监手把手系统带你学产品、学运营。这篇文章暂时不讨论什么是需求文档,也不强调需求文档的重要性等等,就简单地从各种细节问题出发如何写好一份需求文档。一份好...