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 |
python | 3.13 |
pyside6 | 6.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 |
python | 3.13 |
pyside6 | 6.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) # 替换折线序列中的点
相关文章:

Qt图表绘制(QtCharts)- 性能优化(13)
文章目录 1 批量替换代替追加1.1 测试11.2 测试21.3 测试3 2 开启OpenGL2.1 测试12.2 测试22.3 测试32.4 测试4 更多精彩内容👉内容导航 👈👉Qt开发 👈👉QtCharts绘图 👈👉python开发 …...
Spring Cloud动态配置刷新:@RefreshScope与@Component的协同机制解析
在微服务架构中,动态配置管理是实现服务灵活部署、快速响应业务变化的关键能力之一。Spring Cloud 提供了基于 RefreshScope 和 Component 的动态配置刷新机制,使得开发者可以在不重启服务的情况下更新配置。 本文将深入解析 RefreshScope 与 Component…...
部署docker上的redis,idea一直显示Failed to connect to any host resolved for DNS name
参考了https://blog.csdn.net/m0_74216612/article/details/144145127 这篇文章,关闭了centos的防火墙,也修改了redis.conf文件,还是一直显示Failed to connect to any host resolved for DNS name。最终发现是腾讯云服务器那一层防火墙没…...

如何在 Windows 10 或 11 上使用命令提示符安装 PHP
我们可以在 Windows 上从其官方网站下载并安装 PHP 的可执行文件,但使用命令提示符或 PowerShell 更方便。 PHP 并不是一种新的或不为人知的脚本语言,它已经存在并被全球数千名网络开发人员使用。它以开源许可并分发,广泛用于 LAMP 堆栈中。然而,与 Linux 相比,它在 Wind…...

RK3588 ADB使用
安卓adb操作介绍 adb(Android Debug Bridge)是一个用于与安卓设备进行通信和控制的工具。adb可以通过USB或无线网络连接安卓设备,执行各种命令,如安装和卸载应用,传输文件,查看日志,运行shell命…...
Vue 3.0双向数据绑定实现原理
Vue3 的数据双向绑定是通过响应式系统来实现的。相比于 Vue2,Vue3 在响应式系统上做了很多改进,主要使用了 Proxy 对象来替代原来的 Object.defineProperty。本文将介绍 Vue3 数据双向绑定的主要特点和实现方式。 1. 响应式系统 1.1. Proxy对象 Vue3 …...

Please install it with pip install onnxruntime
无论怎么安装都是 Please install it with pip install onnxruntime 我python 版本是3.11 ,我换成3.10 解决了...
java -jar命令运行 jar包时如何运行外部依赖jar包
java -jar命令运行 jar包时如何运行外部依赖jar包 场景: 打包发不完,运行时。发现一个问题, java java.lang.NoClassDefFoundError: org/apache/commons/lang3/ArrayUtils 显示此,基本表明,没有这个依赖,如果在开发…...

低损耗高效能100G O Band DWDM 10km光模块 | 支持密集波分复用
目录 前言 一、产品概述 100G QSFP28 O Band DWDM 10km光模块核心特点包括: 二、为何选择O Band DWDM方案? 1.低色散损耗,传输更稳定 2.兼容性强 三、典型应用场景 1.数据中心互联(DCI) 2.企业园区/智慧城市组网 3.电信…...
【解决分辨数字】2021-12-16
缘由用C语言解决分辨数字-编程语言-CSDN问答 int a 0, w 0, aa[6]{};cin >> a;while (a)aa[w] a % 10, a / 10, w;cout << w << endl;while (a<w)cout << aa[a] << ends, aa[5] * 10, aa[5] aa[a];cout << endl << aa[5] <…...
el-tree结合checkbox实现数据回显
组件代码 <el-tree:data"vertiList"show-checkboxnode-key"id":props"defaultProps"ref"treeRefx"class"custom-tree"check-change"handleCheckChange"> </el-tree>获取选择的节点 handleCheckChan…...

第二十六天打卡
全局变量 global_var 全局变量是定义在函数、类或者代码块外部的变量,它在整个程序文件内都能被访问。在代码里, global_var 就是一个全局变量,下面是相关代码片段: print("\n--- 变量作用域示例 ---") global_var …...

阿里云ECS部署Dify
一:在ECS上面安装Docker 关防火墙 sudo systemctl stop firewalld 检查防火墙状态 systemctl status firewalld sudo yum install -y yum-utils device-mapper-persistent-data lvm2 设置阿里镜像源,安装并启动docker [base] nameCentOS-$releas…...
【线段树】P4588 [TJOI2018] 数学计算|普及+
本文涉及知识点 C线段树 [TJOI2018] 数学计算 题目描述 小豆现在有一个数 x x x,初始值为 1 1 1。小豆有 Q Q Q 次操作,操作有两种类型: 1 m:将 x x x 变为 x m x \times m xm,并输出 x m o d M x \bmod M…...

日志与策略模式
什么是设计模式 IT⾏业 ,为了让 菜鸡们不太拖⼤佬的后腿, 于是⼤佬们针对⼀些经典的常⻅的场景, 给定了⼀些对应的解决⽅案, 这个就是 设计模式 日志认识 计算机中的⽇志是记录系统和软件运⾏中发⽣事件的⽂件,主要作⽤是监控运⾏状态、记录异常信 息ÿ…...

Jenkins 最佳实践
1. 在Jenkins中避免调度过载 过载Jenkins以同时运行多个作业可能导致资源竞争、构建速度变慢和系统性能问题。分配作业启动时间可以防止瓶颈,并确保更顺畅的执行。如何实现? 在Cron表达式中使用H:引入抖动(jitter)&a…...

天能股份SAP系统整合实战:如何用8个月实现零业务中断的集团化管理升级
目录 天能股份SAP系统整合案例:技术驱动集团化管理的破局之路 一、企业背景:新能源巨头的数字化挑战 二、项目难点:制造业的特殊攻坚战 1. 生产连续性刚性需求 2. 数据整合三重障碍 3. 资源限制下的技术突围 三、解决方案:S…...
搜索引擎的高级语法
文章目录 精确搜索:双引号站内搜索:site通配符搜索:*减号缩小范围:-文档搜索:filetypeURL搜索: inurl标题搜索:intitle正文搜索:intext参考链接 精确搜索:双引号 “ ” …...

uniapp-商城-59-后台 新增商品(属性的选中,进行过滤展示,filter,some,every和map)
前面讲了属性的添加,添加完成后,数据库中已经存在数据了,这时再继续商品的添加时,就可以进行属性的选择了。 在商品添加过程中,属性选择是一个关键步骤。首先,界面需要展示嵌套的属性数据,用户通…...
linux用户切换
在 Linux 系统中,/etc/shadow 文件存储了用户的加密密码和其他安全相关信息,因此默认只有 root 用户 才有权限读取。当你尝试用普通用户身份查看时,会收到 Permission denied 错误。 如何查看 /etc/shadow 文件? 方法 1ÿ…...

B2C 商城转型指南:传统企业如何用 ZKmall模板商城实现电商化
在数字化浪潮席卷全球的当下,传统企业向电商转型已不再是选择题,而是关乎生存与发展的必答题。然而,缺乏技术积累、开发成本高、运营经验不足等问题,成为传统企业转型路上的 “拦路虎”。ZKmall模板商城以其低门槛、高灵活、强适配…...
鸿蒙OSUniApp 实现的二维码扫描与生成组件#三方框架 #Uniapp
UniApp 实现的二维码扫描与生成组件 前言 最近在做一个电商小程序时,遇到了需要扫描和生成二维码的需求。在移动应用开发中,二维码功能已经成为标配,特别是在电商、社交和支付等场景下。UniApp作为一个跨平台开发框架,为我们提供…...

生成树协议 - STP
目录 BPDU STP选举机制 STP端口状态 STP计时器 STP拓扑变更机制 生成树协议(Spanning Tree Protocol),简写为STP。 STP是二层网络中用于消除环路的协议,通过阻塞冗余链路,使可用链路在拓扑上呈现出无环的树结构&…...

计算机指令分类和具体的表示的方式
1.关于计算机的指令系统 下面的这个就是我们的一个简单的计算机里面涉及到的指令: m就是我们的存储器里面的地址,可以理解为memory这个意思,r可以理解为rom这样的单词的首字母,帮助我们去进行这个相关的指令的记忆,不…...

mvc-service引入
什么是业务层 1)Model1(JSP)和Model2(模糊的mvc): MVC:Model(模型),View(视图),Controller(控制器) 视图层:用于数据展示以及用户交互的界…...

基于微信小程序的城市特色旅游推荐应用的设计与实现
💗博主介绍💗:✌在职Java研发工程师、专注于程序设计、源码分享、技术交流、专注于Java技术领域和毕业设计✌ 温馨提示:文末有 CSDN 平台官方提供的老师 Wechat / QQ 名片 :) Java精品实战案例《700套》 2025最新毕业设计选题推荐…...

【暗光图像增强】【基于CNN的方法】2020-AAAI-EEMEFN
EEMEFN:Low-Light Image Enhancement via Edge-Enhanced Multi-Exposure Fusion Network EEMEFN:基于边缘增强多重曝光融合网络的低光照图像增强 AAAI 2020 论文链接 0.论文摘要 本研究专注于极低光照条件下的图像增强技术,旨在提升图像亮度…...

【Linux】ssh命令 – 安全的远程连接服务
原创:厦门微思网络 SSH命令的概念 ssh命令的功能是安全地远程连接服务器主机系统,作为OpenSSH套件中的客户端连接工具,ssh命令可以让我们轻松地基于SSH加密协议进行远程主机访问,从而实现对远程服务器的管理工作。 语法 ssh 参…...

AT9850B—单北斗导航定位芯片
AT9850B是一款高性能低功耗双频单北斗卫星导航接收机SOC单芯片。芯片集成射频前端和数字基带、多模式卫星信号处理引擎、电源管理功能,集成度高,外围应用电路简洁。 支持中国北斗B1I/B1C单频定位或B1I/B1C/B2a双频定位,支持北斗二号和三号&a…...
【开源Agent框架】CAMEL:角色扮演+任务分解
一、项目概览:重新定义智能体协作范式 CAMEL(Communicative Agents for “Mind” Exploration of Large Language Model Society)是由camel-ai社区开发的开源多智能体框架,致力于探索智能体的规模法则(Scaling Laws)。该项目通过构建包含百万级智能体的复杂社会系统,研…...