QT、python实现高速动态绘图(基于pyside6、QCharts)

QT、python实现高速动态绘图(基于pyside6、QCharts)


摘要

在python实现使用QCharts绘制高速的动态图(可达5ms数据刷新率),刷新率远远优于Matplotlib。适合配合界面进行实时数据采集的场合,如:工控设备数据采集UI

效果

python 2023-09-30 22-42-25

前言

由于项目需求,需要一个能够高速采集串口数据,并将数据以曲线形式显示出来的界面(ms级刷新率)。笔者曾经使用过matplotlib的animation来绘制,但是由于刷新速度始终无法提高,最终放弃该库。后来机缘巧合的发现了Pyside6里面有个QCharts也可用于绘图,于是尝试了一下,最终效果还不错,于是分享一下实现基本绘图功能的代码。

完整代码

""" 
QChart动态绘图
"""
from PySide6.QtCharts import QChart, QChartView, QLineSeries, QValueAxis
from PySide6.QtGui import QPainter
from PySide6.QtCore import Qt, QTimer, QPointF  # QPointF在QtCore中
from PySide6.QtWidgets import QApplication
import sys
import math
import numpy as np

class SinWaveChart(QChart):
    def __init__(self):
        super().__init__()

        # 显示的时间范围
        self.t_range = 1
        self.Ts = 0.01
        
        # 创建一个序列
        self.series = QLineSeries()
        self.addSeries(self.series)

        # 创建坐标轴
        self.axisX_ = QValueAxis()
        self.axisY_ = QValueAxis()
        self.addAxis(self.axisX_, Qt.AlignBottom)
        self.addAxis(self.axisY_, Qt.AlignLeft)
        self.series.attachAxis(self.axisX_)
        self.series.attachAxis(self.axisY_)
        self.axisX_.setTickCount(11)

        # 初始化x的值
        self.x = 0

        # 设置y轴的范围
        self.axisX_.setMin(self.x)
        self.axisX_.setMax(self.t_range)
        self.axisY_.setMin(-1)
        self.axisY_.setMax(1)

        self.points = []
        self.timer = QTimer()
        self.timer.timeout.connect(self.handleTimeout)
        self.timer.start(self.Ts * 1000)  # 更新频率60帧/秒
        
        self.resize(500,500)

    def handleTimeout(self):
        y = math.sin(2*np.pi*self.x)
        self.points.append(QPointF(self.x, y))  # 创建QPointF对象

        self.x += self.Ts

        if self.x > self.t_range:
            self.axisX_.setRange(self.x - self.t_range, self.x - self.Ts)
            self.points = self.points[-int(self.t_range/self.Ts):]

        self.series.replace(self.points)  # 使用replace()替换整个数据集

if __name__ == "__main__":
    app = QApplication(sys.argv)

    chart = SinWaveChart()
    chart.legend().hide()
    chart.setTitle("Dynamic sin wave")

    chart_view = QChartView(chart)
    chart_view.setRenderHint(QPainter.Antialiasing)

    chart_view.show()

    sys.exit(app.exec())
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【资源介绍】 基于PySide6框架+python的智能充电桩调度计费系统前端源码+项目说明文档.zip 基于 PySide6 框架与 Python3.10 开发。 开发环境配置 下载安装 Python3.10(Windows 建议使用微软商店) 克隆项目仓库 在项目根目录执行 python3.10 -m pip install -r requirements.txt 使用 python3.10 admin/main.py 与 python3.10 user/main.py 分别启动用户客户端与管理员客户端程序 调试方法 调试 AcssFrontend 的方法与调试 AcssBackend 的方法一致 使用 Visual Studio Code 打开本项目,并点击右下角 Python 版本切换至 Python3.10 在调试选项中选择 Python 文件 并创建 launch.json 在希望调试的位置添加断点 使用功能键 F5 启动调试 代码要求 不可以在代码中使用同步阻塞操作,例如 sleep(1); 所有阻塞操作均需要使用使用支持 asyncio 的函数,并在函数前添加 await 关键字; 使用 await 关键字的函数 def 前需要添加 async 关键字。 基本代码逻辑说明 程序入口模块 main.py 这里执行一些基本初始化操作,并且定义按钮点击事件的响应函数,并将它们绑定到 Qt 控件上。 Qt 以阻塞的方式调用 Python 函数,所以直接在函数中执行网络IO是不可行的(等待响应的过程用户界面会失去响应),所以这里使用 qasync 模块兼容了 Python 的异步框架 asyncio。通过这种方法,所有阻塞操作全部可以使用异步方式调用,这样就不会阻塞用户界面了。异步调用示例如下: import api import qasync @qasync.asyncSlot() async def on_login_clicked(): try: kwargs = await api.login('jinuo', 'i-hate-bupt') except ApiError as e: some_toast(str(e)).show() token = kwargs['token'] is_admin = kwargs['is_admin'] # rest codes 响应函数调用 API 模块提供的函数以与服务端进行交互。捕获 ApiError 并显示提示框,若未发生异常则从返回值中获取服务器返回的数据,并对用户界面进行相应的更新。 主窗口模块 mainwindow.py 该模块负责加载窗口,并保存控件的 Python 对象。显然这样的写法不是最佳实践,我没有花时间找到加载UI文件并继承 QWidget 类的方法(又不是不能用)。 API 模块 api.py 所有对网络的调用全部在 API 模块内完成。 API 模块内的 api_post 与 api_get 两个函数封装了 requests 库的 get 与 post 操作。这两个函数需要能够自动在其中添加 Authorization 请求头。 api_post 与 api_get 中使用 requests 模块时,需要捕获网络 IO 异常(如超时),并且使用 raise ApiError("网络异常") from e 将相关异常以 ApiError 异常的类型抛出。 api_post 与 api_get 在获取到响应时,需要判断 code 是否为 0,为 -1 时需要抛出 ApiError(response['message']) 异常。 API 模块除 api_post 与 api_get 的函数与 开放 API 文档 内的接口一一对应,需要调用 api_post 与 api_get 对服务端发起请求。 这些函数不需要捕获 ApiError 异常,对异常的捕获应该发生在 API 模块的调用者处,以决定是否要反馈到用户界面中(Toast)。 调用者捕获到 ApiError 异常时,仅需要使用 str(e) 即可获取到异常的文本信息, 该项目是个人毕设项目,答辩评审分达到95分,代码都经过调试测试,确保可以运行!欢迎下载使用,可用于小白学习、进阶。 该资源主要针对计算机、通信、人工智能、自动化等相关专业的学生、老师或从业者下载使用,亦可作为期末课程设计、课程大作业、毕业设计等。 项目整体具有较高的学习借鉴价值!基础能力强的可以在此基础上修改调整,以实现不同的功能。 欢迎下载交流,互相学习,共同进步!
为了使用Pyside6进行鼠标绘图,你可以按照以下步骤进行操作: 1. 首先,在Python中安装Pyside6库和Qt Material库(使用pip install pyside6和pip install qt_material命令)。 2. 创建一个新的Python文件,并导入必要的模块。例如,你可以导入PySide6的QtWidgets模块来创建应用程序窗口。 3. 在你的Python文件中,创建一个新的类来继承自QtWidgets.QMainWindow和你的主窗口类(通常是Ui_MainWindow类)[3]。在这个类中,你可以定义自己的绘图函数。 4. 在你的主窗口类的构造函数中,调用父类的构造函数,并通过self.setupUi(self)和self.retranslateUi(self)方法初始化主窗口的界面。 5. 定义一个鼠标事件处理函数,例如mousePressEvent()或mouseMoveEvent()。你可以在这些函数中获取鼠标的坐标,并根据需要进行绘图操作。 6. 在主窗口类中,连接鼠标事件信号与鼠标事件处理函数。你可以使用PySide6的信号和槽机制,例如使用QObject.connect()方法或在Qt Designer中使用QMetaObject.connectSlotsByName()方法。 7. 最后,在main函数中创建应用程序对象,并显示主窗口。使用app.exec()方法来启动应用程序的事件循环,以响应用户的交互。 通过按照上述步骤,你可以在Pyside6中实现鼠标绘图功能。记得根据你的具体需求,在绘图函数中添加相应的绘图逻辑。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [【PythonPyside6简易版教程](https://blog.csdn.net/SpriteNym/article/details/127927687)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [我用Python+PySide6做了个图形化番茄钟,这下可以提醒自己放松一下了。](https://blog.csdn.net/m0_60397533/article/details/125587188)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值