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

使用PyQtGraph 自定义绘图

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

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官方更详细的文档和实例程序。

相关推荐

如何设计一个优秀的电子商务产品详情页

加入人人都是产品经理【起点学院】产品经理实战训练营,BAT产品总监手把手带你学产品电子商务网站的产品详情页面无疑是设计师和开发人员关注的最重要的网页之一。产品详情页面是客户作出“加入购物车”决定的页面...

怎么在JS中使用Ajax进行异步请求?

大家好,今天我来分享一项JavaScript的实战技巧,即如何在JS中使用Ajax进行异步请求,让你的网页速度瞬间提升。Ajax是一种在不刷新整个网页的情况下与服务器进行数据交互的技术,可以实现异步加...

中小企业如何组建,管理团队_中小企业应当如何开展组织结构设计变革

前言写了太多关于产品的东西觉得应该换换口味.从码农到架构师,从前端到平面再到UI、UE,最后走向了产品这条不归路,其实以前一直再给你们讲.产品经理跟项目经理区别没有特别大,两个岗位之间有很...

前端监控 SDK 开发分享_前端监控系统 开源

一、前言随着前端的发展和被重视,慢慢的行业内对于前端监控系统的重视程度也在增加。这里不对为什么需要监控再做解释。那我们先直接说说需求。对于中小型公司来说,可以直接使用三方的监控,比如自己搭建一套免费的...

Ajax 会被 fetch 取代吗?Axios 怎么办?

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!今天给大家带来的主题是ajax、fetch...

前端面试题《AJAX》_前端面试ajax考点汇总

1.什么是ajax?ajax作用是什么?AJAX=异步JavaScript和XML。AJAX是一种用于创建快速动态网页的技术。通过在后台与服务器进行少量数据交换,AJAX可以使网页实...

Ajax 详细介绍_ajax

1、ajax是什么?asynchronousjavascriptandxml:异步的javascript和xml。ajax是用来改善用户体验的一种技术,其本质是利用浏览器内置的一个特殊的...

6款可替代dreamweaver的工具_替代powerdesigner的工具

dreamweaver对一个web前端工作者来说,再熟悉不过了,像我07年接触web前端开发就是用的dreamweaver,一直用到现在,身边的朋友有跟我推荐过各种更好用的可替代dreamweaver...

我敢保证,全网没有再比这更详细的Java知识点总结了,送你啊

接下来你看到的将是全网最详细的Java知识点总结,全文分为三大部分:Java基础、Java框架、Java+云数据小编将为大家仔细讲解每大部分里面的详细知识点,别眨眼,从小白到大佬、零基础到精通,你绝...

福斯《死侍》发布新剧照 "小贱贱"韦德被改造前造型曝光

时光网讯福斯出品的科幻片《死侍》今天发布新剧照,其中一张是较为罕见的死侍在被改造之前的剧照,其余两张剧照都是死侍在执行任务中的状态。据外媒推测,片方此时发布剧照,预计是为了给不久之后影片发布首款正式预...

2021年超详细的java学习路线总结—纯干货分享

本文整理了java开发的学习路线和相关的学习资源,非常适合零基础入门java的同学,希望大家在学习的时候,能够节省时间。纯干货,良心推荐!第一阶段:Java基础重点知识点:数据类型、核心语法、面向对象...

不用海淘,真黑五来到你身边:亚马逊15件热卖爆款推荐!

Fujifilm富士instaxMini8小黄人拍立得相机(黄色/蓝色)扫二维码进入购物页面黑五是入手一个轻巧可爱的拍立得相机的好时机,此款是mini8的小黄人特别版,除了颜色涂装成小黄人...

2025 年 Python 爬虫四大前沿技术:从异步到 AI

作为互联网大厂的后端Python爬虫开发,你是否也曾遇到过这些痛点:面对海量目标URL,单线程爬虫爬取一周还没完成任务;动态渲染的SPA页面,requests库返回的全是空白代码;好不容易...

最贱超级英雄《死侍》来了!_死侍超燃

死侍Deadpool(2016)导演:蒂姆·米勒编剧:略特·里斯/保罗·沃尼克主演:瑞恩·雷诺兹/莫蕾娜·巴卡林/吉娜·卡拉诺/艾德·斯克林/T·J·米勒类型:动作/...

停止javascript的ajax请求,取消axios请求,取消reactfetch请求

一、Ajax原生里可以通过XMLHttpRequest对象上的abort方法来中断ajax。注意abort方法不能阻止向服务器发送请求,只能停止当前ajax请求。停止javascript的ajax请求...