Qt图表绘制(QtCharts)- 性能优化(13)

文章目录

    • 1 批量替换代替追加
      • 1.1 测试1
      • 1.2 测试2
      • 1.3 测试3
    • 2 开启OpenGL
      • 2.1 测试1
      • 2.2 测试2
      • 2.3 测试3
      • 2.4 测试4


更多精彩内容
👉内容导航 👈
👉Qt开发 👈
👉QtCharts绘图 👈
👉python开发 👈

1 批量替换代替追加

环境说明
系统windows10
python3.13
pyside66.8.3
性能分析工具line_profiler_pycharm
  • 如下所示,使用replace添加数据和使用append添加数据性能对比,单次添加数据越多,replace性能比append越强

  • 示例代码

    import random  # 导入random模块,用于生成随机数
    import sysfrom PySide6.QtCharts import QChart, QChartView, QLineSeries, QValueAxis  # 导入QtCharts模块,用于创建图表和轴
    from PySide6.QtCore import QTimer  # 导入QTimer,用于定时更新图表
    from PySide6.QtCore import Qt  # 导入Qt核心模块,用于设置对齐方式等
    from PySide6.QtGui import QPainter  # 导入QPainter,用于设置图表的渲染提示
    from PySide6.QtWidgets import QApplication, QMainWindow  # 导入PySide6的QApplication和QMainWindow类
    from line_profiler_pycharm import profile
    from PySide6.QtCore import QPointFclass MainWindow(QMainWindow):  # 定义MainWindow类,继承自QMainWindowdef __init__(self):super().__init__()  # 调用父类的构造函数self.setWindowTitle("PySide6 折线图示例")  # 设置窗口标题self.setGeometry(100, 100, 800, 600)  # 设置窗口的位置和大小self.timer = QTimer()  # 创建一个定时器self.timer.timeout.connect(self.update_chart)  # 连接定时器超时信号到update_chart方法self.timer.start(10)  # 设置定时器间隔为10毫秒,并启动定时器# print(help(QChart))  # 这行代码可以用于打印QChart类的帮助信息,目前被注释掉了self.chart_view = None  # 初始化图表视图为Noneself.series1 = QLineSeries()  # 创建一个折线序列对象self.series2 = QLineSeries()  # 创建一个折线序列对象# self.series1.setUseOpenGL(True)  # 设置折线序列使用OpenGL渲染# self.series2.setUseOpenGL(True)  # 设置折线序列使用OpenGL渲染self.init_chart()  # 调用初始化图表的方法def init_chart(self):  # 定义初始化图表的方法# 设置名称self.series1.setName("series1")  # 设置折线的名称self.series2.setName("series2")  # 设置折线的名称# 创建图表chart = QChart()  # 创建一个图表对象chart.addSeries(self.series1)  # 将折线序列添加到图表中chart.addSeries(self.series2)  # 将折线序列添加到图表中chart.setTitle("简单的折线图")  # 设置图表的标题# chart.setAnimationOptions(QChart.AnimationOption.SeriesAnimations)  # 设置图表不使用动画# 创建x轴和y轴axis_x = QValueAxis()  # 创建一个数值型x轴axis_y = QValueAxis()  # 创建一个数值型y轴chart.addAxis(axis_x, Qt.AlignmentFlag.AlignBottom)  # 将x轴添加到图表底部chart.addAxis(axis_y, Qt.AlignmentFlag.AlignLeft)  # 将y轴添加到图表左侧self.series1.attachAxis(axis_x)  # 将折线序列附着到x轴self.series1.attachAxis(axis_y)  # 将折线序列附着到y轴self.series2.attachAxis(axis_x)  # 将折线序列附着到x轴self.series2.attachAxis(axis_y)  # 将折线序列附着到y轴# 创建图表视图self.chart_view = QChartView(chart)  # 创建一个图表视图对象,并将图表添加进去self.chart_view.setRenderHint(QPainter.RenderHint.Antialiasing)  # 设置图表视图的渲染提示为抗锯齿# 设置主窗口的中心部件self.setCentralWidget(self.chart_view)  # 设置主窗口的中心部件为图表视图@profiledef update_chart1(self):  # 定义更新图表的方法"""使用append方法更新折线序列:return: """for i in range(10):  # 循环10次random_integer = random.randint(1, 100)  # 生成一个1到100之间的随机整数self.series1.append(self.series1.count(), random_integer)  # 将新的点添加到折线序列中chart = self.chart_view.chart()  # 获取图表视图中的图表对象axis_x = chart.axes(Qt.Orientation.Horizontal)[0]  # 获取图表中的x轴对象axis_y = chart.axes(Qt.Orientation.Vertical)[0]  # 获取图表中的y轴对象axis_x.setRange(0, self.series1.count())  # 设置x轴的范围,使其从0到当前折线序列点的数量axis_y.setRange(0, 100)  # 设置y轴的范围,使其从0到100@profiledef update_chart2(self):  """使用replace方法更新折线序列:return: """data = self.series2.points()for i in range(10):  # 循环10次random_integer = random.randint(1, 100)  # 生成一个1到100之间的随机整数data.append(QPointF(len(data), random_integer))  # 将新的点添加到折线序列中self.series2.replace(data)  # 替换折线序列中的点chart = self.chart_view.chart()  # 获取图表视图中的图表对象axis_x = chart.axes(Qt.Orientation.Horizontal)[0]  # 获取图表中的x轴对象axis_y = chart.axes(Qt.Orientation.Vertical)[0]  # 获取图表中的y轴对象axis_x.setRange(0, self.series2.count())  # 设置x轴的范围,使其从0到当前折线序列点的数量axis_y.setRange(0, 100)  # 设置y轴的范围,使其从0到100@profiledef update_chart(self):  # 定义更新图表的方法self.update_chart1()  # 调用更新图表的方法self.update_chart2()  # 调用更新图表的方法if __name__ == "__main__":  # 确保只有在直接运行此脚本时才会执行下面的代码app = QApplication(sys.argv)  # 创建一个QApplication对象window = MainWindow()  # 创建一个MainWindow对象window.show()  # 显示主窗口sys.exit(app.exec())  # 进入应用程序的主循环,并等待退出

1.1 测试1

  • 测试方法:定时器1秒刷新1次,每次在循环中添加10个点数据;
  • 测试结果:
    • 从整个函数看update_chart1耗时是update_chart2的6.5倍;
    • 从单行代码看append耗时是replace的11.3倍;

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1.2 测试2

  • 测试方法:定时器1秒刷新1次,每次在循环中添加1000个点数据;
  • 测试结果:
    • 从整个函数看update_chart1耗时是update_chart2的199倍;
    • 从单行代码看append耗时是replace的750倍;

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

1.3 测试3

  • 测试方法:定时器10毫秒刷新1次,每次在循环中添加10个点数据;
  • 测试结果:
    • 从整个函数看update_chart1耗时是update_chart2的5.57倍;
    • 从单行代码看append耗时是replace的8.82倍;

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

2 开启OpenGL

环境说明
系统windows10
python3.13
pyside66.8.3
性能分析工具line_profiler_pycharm
  • 如下所示,对比开启OpenGL和开启OpenGL的性能区别;当使用appeng添加数据时,开启opengl和不开opengl的区别最大;

  • 示例代码:

    import random  # 导入random模块,用于生成随机数
    import sysfrom PySide6.QtCharts import QChart, QChartView, QLineSeries, QValueAxis  # 导入QtCharts模块,用于创建图表和轴
    from PySide6.QtCore import QTimer  # 导入QTimer,用于定时更新图表
    from PySide6.QtCore import Qt  # 导入Qt核心模块,用于设置对齐方式等
    from PySide6.QtGui import QPainter  # 导入QPainter,用于设置图表的渲染提示
    from PySide6.QtWidgets import QApplication, QMainWindow  # 导入PySide6的QApplication和QMainWindow类
    from line_profiler_pycharm import profile
    from PySide6.QtCore import QPointFclass MainWindow(QMainWindow):  # 定义MainWindow类,继承自QMainWindowdef __init__(self):super().__init__()  # 调用父类的构造函数self.setWindowTitle("PySide6 折线图示例")  # 设置窗口标题self.setGeometry(100, 100, 800, 600)  # 设置窗口的位置和大小self.timer = QTimer()  # 创建一个定时器self.timer.timeout.connect(self.update_chart)  # 连接定时器超时信号到update_chart方法self.timer.start(1000)  # 设置定时器间隔为10毫秒,并启动定时器self.chart_view = None  # 初始化图表视图为Noneself.series1 = QLineSeries()  # 创建一个折线序列对象self.series2 = QLineSeries()  # 创建一个折线序列对象self.series1.setUseOpenGL(True)  # 设置折线序列使用OpenGL渲染# self.series2.setUseOpenGL(True)  # 设置折线序列使用OpenGL渲染self.init_chart()  # 调用初始化图表的方法def init_chart(self):  # 定义初始化图表的方法# 设置名称self.series1.setName("series1")  # 设置折线的名称self.series2.setName("series2")  # 设置折线的名称# 创建图表chart = QChart()  # 创建一个图表对象chart.addSeries(self.series1)  # 将折线序列添加到图表中chart.addSeries(self.series2)  # 将折线序列添加到图表中chart.setTitle("简单的折线图")  # 设置图表的标题# chart.setAnimationOptions(QChart.AnimationOption.SeriesAnimations)  # 设置图表不使用动画# 创建x轴和y轴axis_x = QValueAxis()  # 创建一个数值型x轴axis_y = QValueAxis()  # 创建一个数值型y轴axis_y.setRange(0, 100)  # 设置y轴的范围,使其从0到100chart.addAxis(axis_x, Qt.AlignmentFlag.AlignBottom)  # 将x轴添加到图表底部chart.addAxis(axis_y, Qt.AlignmentFlag.AlignLeft)  # 将y轴添加到图表左侧self.series1.attachAxis(axis_x)  # 将折线序列附着到x轴self.series1.attachAxis(axis_y)  # 将折线序列附着到y轴self.series2.attachAxis(axis_x)  # 将折线序列附着到x轴self.series2.attachAxis(axis_y)  # 将折线序列附着到y轴# 创建图表视图self.chart_view = QChartView(chart)  # 创建一个图表视图对象,并将图表添加进去self.chart_view.setRenderHint(QPainter.RenderHint.Antialiasing)  # 设置图表视图的渲染提示为抗锯齿# 设置主窗口的中心部件self.setCentralWidget(self.chart_view)  # 设置主窗口的中心部件为图表视图@profiledef update_chart1(self):  # 定义更新图表的方法"""开启OpenGL渲染,使用append方法更新折线序列:return:"""for i in range(10):  # 循环10次random_integer = random.randint(1, 100)  # 生成一个1到100之间的随机整数self.series1.append(self.series1.count(), random_integer)  # 将新的点添加到折线序列中@profiledef update_chart2(self):"""不开启OpenGL渲染,使用append方法更新折线序列:return:"""for i in range(10):  # 循环10次random_integer = random.randint(1, 100)  # 生成一个1到100之间的随机整数self.series2.append(self.series2.count(), random_integer)  # 将新的点添加到折线序列中@profiledef update_chart(self):  # 定义更新图表的方法self.update_chart1()  # 调用更新图表的方法self.update_chart2()  # 调用更新图表的方法chart = self.chart_view.chart()  # 获取图表视图中的图表对象axis_x = chart.axes(Qt.Orientation.Horizontal)[0]  # 获取图表中的x轴对象max_x = self.series2.count()axis_x.setRange(0, max_x)  # 设置x轴的范围,使其从0到当前折线序列点的数量if __name__ == "__main__":  # 确保只有在直接运行此脚本时才会执行下面的代码app = QApplication(sys.argv)  # 创建一个QApplication对象window = MainWindow()  # 创建一个MainWindow对象window.show()  # 显示主窗口sys.exit(app.exec())  # 进入应用程序的主循环,并等待退出

2.1 测试1

  • 测试方法:定时器1秒刷新1次,每次在循环中添加10个点数据;
  • 测试结果:
    • 从整个函数看update_chart2耗时是update_chart1的9.7倍;
    • 从单行代码看append添加数据不开启opengl耗时是开启opengl的21.3倍;

在这里插入图片描述

2.2 测试2

  • 测试方法:定时器1秒刷新1次,每次在循环中添加1000个点数据;
  • 测试结果:
    • 从整个函数看update_chart2耗时是update_chart1的123倍;
    • 从单行代码看append添加数据不开启opengl耗时是开启opengl的169倍;

在这里插入图片描述

2.3 测试3

  • 测试方法:定时器10毫秒刷新1次,每次在循环中添加10个点数据;
  • 测试结果:
    • 从整个函数看update_chart2耗时是update_chart1的72.5倍;
    • 从单行代码看append添加数据不开启opengl耗时是开启opengl的113倍;

在这里插入图片描述

2.4 测试4

  • 测试方法:将使用append添加数据改为使用replace添加数据,定时器10毫秒刷新1次,每次在循环中添加10个点数据;

  • 测试结果:

    • 从整个函数看update_chart2耗时是update_chart1的1.84倍;
    • 从单行代码看replace添加数据不开启opengl耗时是开启opengl的11倍;
  • 测试代码:

        @profiledef update_chart1(self):  # 定义更新图表的方法"""开启OpenGL渲染,使用append方法更新折线序列:return:"""data = self.series1.points()for i in range(10):  # 循环10次random_integer = random.randint(1, 100)  # 生成一个1到100之间的随机整数data.append(QPointF(len(data), random_integer))  # 将新的点添加到折线序列中self.series1.replace(data)  # 替换折线序列中的点@profiledef update_chart2(self):"""不开启OpenGL渲染,使用append方法更新折线序列:return:"""data = self.series2.points()for i in range(10):  # 循环10次random_integer = random.randint(1, 100)  # 生成一个1到100之间的随机整数data.append(QPointF(len(data), random_integer))  # 将新的点添加到折线序列中self.series2.replace(data)  # 替换折线序列中的点
    

在这里插入图片描述



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/905775.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

嵌入式故障码管理系统设计实现

文章目录 前言一、故障码管理系统概述二、核心数据结构设计2.1 故障严重等级定义2.2 模块 ID 定义2.3 故障代码结构2.4 故障记录结构 三、故障管理核心功能实现3.1 初始化功能3.2 故障记录功能3.3 记录查询与清除功能3.4 系统自检功能 四、故障存储实现4.1 Flash 存储实现4.2 R…

动态规划-63.不同路径II-力扣(LeetCode)

一、题目解析 与62.不同路径不同的一点是现在网格中有了障碍物,其他的并没有什么不同 二、算法解析 1.状态表示 dp[i][j]表示:到[i,j]位置时,不同的路径数 2.状态转移方程 由于多了障碍物,所以我们要判断是否遇到障碍物 3.初…

使用CherryStudio +SiliconFlow 部署独立的deepseek+知识库

deepseek知识库,独立的deepseek 首先我们先了解 CherryStudio?SiliconFlow? CherryStudio是一个支持多平台的AI客户端,我们致力于让更多人能够享受到AI带来的便利。 简单来说,它是一个能让普通人轻松用上AI 的「万能工…

Openshift节点Disk pressure

OpenShift 监控以下指标,并定义以下垃圾回收的驱逐阈值。请参阅产品文档以更改任何驱逐值。 nodefs.available 从 cadvisor 来看,该node.stats.fs.available指标表示节点文件系统(所在位置)上有多少可用(剩余&#xf…

MySQL的 JOIN 优化终极指南

目录 前言序章:为何要有JOIN?——“一个好汉三个帮”的数据库哲学 🤝第一章:JOIN的“七十二变”——常见JOIN类型速览 🎭第二章:MySQL的“红娘秘籍”——JOIN执行原理大揭秘 🕵️‍♀️&#x1…

TLS 1.3黑魔法:从协议破解到极致性能调优

一、TLS协议逆向工程实验 1.1 密码学套件破解剧场 实验准备: 靶机:启用TLS 1.2的Nginx服务器 工具集:Wireshark OpenSSL s_client 定制Python脚本 实战攻击复现: # 强制使用弱加密套件连接 openssl s_client -connect exa…

国标GB/T 12536-90滑行试验全解析:纯电动轻卡行驶阻力模型参数精准标定

摘要 本文以国标GB/T 12536-90为核心框架,深度解析纯电动轻卡滑行试验的完整流程与数据建模方法,提供: 法规级试验规范:从环境要求到数据采集全流程详解行驶阻力模型精准标定:最小二乘法求解 ( FAv^2BvC ) 的MATLAB实…

【GaussDB迁移攻略】DRS支持CDC,解决大规模数据迁移挑战

目录 1 背景介绍 2 CDC的实现原理 3 DRS的CDC实现方式 4 DRS的CDC使用介绍 5 总结 1 背景介绍 随着国内各大行业数字化转型的加速,客户的数据同步需求越来越复杂。特别是当需要将一个源数据库的数据同时迁移到不同的目标库场景时,华为云通常会创建…

PSA Certified

Arm 推出的 PSA Certified 已成为安全芯片设计领域的黄金标准。通过对安全启动、加密服务以及更新协议等方面制定全面的要求,PSA Certified为芯片制造商提供了清晰的路线图,使其能将安全机制深植于定制芯片解决方案的基础架构中。作为对PSA Certified的补…

游戏引擎学习第286天:开始解耦实体行为

回顾并为今天的内容定下基调 我们目前正在进入实体系统的一个新阶段,之前我们已经让实体的移动系统变得更加灵活,现在我们想把这个思路继续延伸到实体系统的更深层次。今天的重点,是重新审视我们处理实体类型(entity type&#x…

遥感图像非法采矿矿区识别分割数据集labelme格式1818张3类别

数据集格式:labelme格式(不包含mask文件,仅仅包含jpg图片和对应的json文件) 图片数量(jpg文件个数):1818 标注数量(json文件个数):1818 标注类别数:3 标注类别名称:["river","illegal-mining"…

python爬虫实战训练

前言:哇,今天终于能访问豆瓣了,前几天爬太多次了,网页都不让我访问了(要登录)。 先来个小练习试试手吧! 爬取豆瓣第一页(多页同上篇文章)所有电影的排名、电影名称、星…

Go语言实现生产者-消费者问题的多种方法

Go语言实现生产者-消费者问题的多种方法 生产者-消费者问题是并发编程中的经典问题,涉及多个生产者生成数据,多个消费者消费数据,二者通过缓冲区(队列)进行协调,保证数据的正确传递和同步。本文将从简单到…

【Opencv】canny边缘检测提取中心坐标

采用opencv 对图像中的小球通过canny边缘检测的方式进行提取坐标 本文介绍了如何使用OpenCV对图像中的小球进行Canny边缘检测,并通过Zernike矩进行亚像素边缘检测,最终拟合椭圆以获取小球的精确坐标。首先,图像被转换为灰度图并进行高斯平滑…

蓝桥杯12届国B 123

题目描述 小蓝发现了一个有趣的数列,这个数列的前几项如下: 1,1,2,1,2,3,1,2,3,4,⋯ 小蓝发现,这个数列前 1 项是整数 1,接下来 2 项是整数 1 至 2,接下来 3 项是整数 1 至 3,接下来 4 项是整数 1 至 4&…

鸿蒙OSUniApp 制作动态加载的瀑布流布局#三方框架 #Uniapp

使用 UniApp 制作动态加载的瀑布流布局 前言 最近在开发一个小程序项目时,遇到了需要实现瀑布流布局的需求。众所周知,瀑布流布局在展示不规则尺寸内容(如图片、商品卡片等)时非常美观和实用。但在实际开发过程中,我…

ThinkStation图形工作站进入BIOS方法

首先视频线需要接在独立显卡上,重新开机,持续按F1,或者显示器出来lenovo的logo的时候按F1,这样就进到bios里了。联*想*坑,戴尔贵。靠。

【源码级开发】Qwen3接入MCP,企业级智能体开发实战!

Qwen3接入MCP智能体开发实战(上) 一、MCP技术与Qwen3原生MCP能力介绍 1.智能体开发核心技术—MCP 1.1 Function calling技术回顾 如何快速开发一款智能体应用,最关键的技术难点就在于如何让大模型高效稳定的接入一些外部工具。而在MCP技术…

Linux下载与安装

一、YUM 1.1 什么是YUM 在CentOS系统中,软件管理方式通常有三种方式:rpm安装、yum安装以及编译(源码)安装。 编译安装,从过程上来讲比较麻烦,包需要用户自行下载,下载的是源码包,需…

PostgreSQL中的全页写

一、概述 在PGSQL数据库中,默认的页面大小为8KB,但是磁盘buffer的大小为4KB,扇区大小为512B。这就导致在操作系统的角度看数据库的写操作,其实并不是一种原子操作。如果操作系统发生了系统级别的故障,此时正好操作系统…