尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

手写一个基于Qt的轻量级示波器界面,附源码

手写一个基于Qt的轻量级示波器界面,附源码
📅 发布时间:2026/6/25 15:57:41

大家好,今天分享一个轻量级类示波器UI界面,基于Qt+C/C++实现,可轻松处理数十万甚至百万数据点绘制而不卡顿。

因一个项目需要显示高速AD采集的仿真波形,采用普通QChart和QCustomPlot实现时,若前端采集速率拉满,UI界面瞬间卡成PPT。

还要支持缩放、游标测量等功能,用现成控件改起来比较麻烦。

所以我自己基于QPainter + RingBuffer封装了一个轻量级waveWidget。

在Demo中并不是将数据简单地画出来,而是实现了一个接近示波器交互体验的波形显示控件:

  • 支持实时刷新、滚动缓存

  • 普通滚轮:Y轴缩放

  • Ctrl + 滚轮:X轴缩放

  • X轴索引、Y轴数值实时显示

  • Marker测量 ΔX / ΔY

  • 双击窗口放大、缩小功能

  • 支持右键菜单操作,可添加自定义功能

话不多说,先上图看效果:

主界面实时显示(可同时支持多通道)

普通滚轮:Y轴缩放

Ctrl + 滚轮:X轴缩放

双击放大缩小选中窗口

标记测量 ΔX / ΔY

支持右键菜单操作,可添加自定义功能

下面简单讲述下部分实现代码,文章底部提供完整实现源码,可直接拷贝到项目工程使用。

waveWidget继承自QWidget,整个控件可以分成三层:数据层(Buffer)、渲染层(Painter)、交互层(Mouse Event),这三个层次分离得比较清楚,后续扩展会很方便。

在数据处理时抛弃传统的 vector.push_back(),采用环形缓冲区设计,当缓冲区未满时正常写入,缓冲区满则自动覆盖最旧数据。

最大占用内存固定化,写入复杂度 O(1),避免大数据量下性能下降,非常适合高频采样场景。

数据写入显示逻辑:

void WaveWidget::appendData(float value) { m_buffer[m_writePos] = value; m_writePos = (m_writePos + 1) % m_capacity; if (m_count < m_capacity) m_count++; update(); }

主体绘制分为四层:背景、网格、波形、交互元素,比全部塞进 paintEvent 可维护高很多。

drawGrid(p); drawWave(p); drawMarkers(p); drawCursor(p);

对于底层的FPGA研发或信号处理工程师来说,光能看到波形是远远不够的,必须能精确地测量出时序。为此,还重写了鼠标与滚轮事件。

动态缩放:在 wheelEvent 中,监听修饰键,按下Ctrl + 滚轮,修改 m_viewSizeX 进行 X 轴时间基准缩放。纯滚轮则修改 m_yScale 控制 Y 轴幅度比例。所有的缩放都是通过纯数学映射完成,不涉及任何底层数据的重新拷贝。

void WaveWidget::wheelEvent(QWheelEvent *e) { if (e->modifiers() & Qt::ControlModifier) { setXView(m_viewSizeX * ((e->angleDelta().y() > 0) ? 0.8 : 1.25)); } else { setYScale(m_yScale * ((e->angleDelta().y() > 0) ? 1.1 : 0.9)); } }

右键工程菜单与卡尺测量:通过重写 contextMenuEvent ,组件支持呼出原生右键菜单,可以随时在波形上打下两根 X 轴(黄色)或 Y 轴(青色)标记线。

void WaveWidget::contextMenuEvent(QContextMenuEvent *e) { if (!m_contextMenu) { m_contextMenu = new QMenu(this); m_contextMenu->addAction("添加 X 标记", [this]() { if(m_markX.size()>=2) m_markX.clear(); m_markX.append(m_selectedIndex); update(); }); m_contextMenu->addAction("添加 Y 标记", [this]() { if(m_markY.size()>=2) m_markY.clear(); m_markY.append((height()/2.0 - m_mousePos.y())/m_yScale); update(); }); m_contextMenu->addAction("清除标记", [this](){ m_markX.clear(); m_markY.clear(); update(); }); } m_contextMenu->exec(e->globalPos()); }

实时差值计算:在drawMarkers函数中,代码会自动执行 abs( m_markX[1] - m_markX[0]) 计算出X轴的采样点差值,以及利用 fabs(m_markY[1] - m_markY[0])计算出Y轴的幅度差值,并高亮显示在左上角。

void WaveWidget::drawMarkers(QPainter &p) { double xStep = (double)width() / (m_viewSizeX - 1); p.setPen(QPen(Qt::yellow, 1)); for (int lx : m_markX) { double px = width() - (m_count - 1 - lx) * xStep; p.drawLine(px, 0, px, height()); } p.setPen(QPen(Qt::cyan, 1)); for (double vy : m_markY) { double py = height() / 2.0 - vy * m_yScale; p.drawLine(0, py, width(), py); } // 绘制结果文字 p.setPen(Qt::white); if (m_markX.size() == 2) p.drawText(10, 20, QString("ΔX: %1").arg(abs(m_markX[1] - m_markX[0]))); if (m_markY.size() == 2) p.drawText(10, 40, QString("ΔY: %1").arg(fabs(m_markY[1] - m_markY[0]), 0, 'f', 3)); }

双击处理:重载mouseDouble ClickEvent(),当双击时发送信号,把业务逻辑交给外部处理。

void WaveWidget::mouseDoubleClickEvent(QMouseEvent *e) { if (e->button() == Qt::LeftButton) { emit doubleClicked(); // 发出双击信号 } QWidget::mouseDoubleClickEvent(e); }

很多时候,真正好用的工具,不一定复杂,但一定贴近实际需求。在工业级的测控系统与高速数据采集中,性能的瓶颈往往就隐藏在一次不经意的深拷贝,或者一次冗余的屏幕擦除中。掌握了底层 UI 渲染的机制,即使面对 GB/s 的吞吐数据,也能稳如泰山。

嵌入式软硬件系统

专注于嵌入式软硬件相关经验分享、工程实践与技术探索,涵盖单片机、FPGA、PCIe、驱动开发、上位机软件以及测控系统设计等多方面内容。

相关新闻

  • SDKMAN CLI:用 Go 重写版本管理工具的探索
  • 博客系统接口需求分析:从模块拆解到自动化测试设计
  • 机器学习小数据训练实战:四维评估与高效落地方法

最新新闻

  • 强化学习工业落地五篇核心论文实战指南
  • 半导体企业如何构建业务连续性管理体系:从ISO 22301到NXP实践
  • Space Thumbnails:智能3D模型文件预览工具在Windows资源管理器中的一站式解决方案
  • Grafana路径遍历漏洞CVE-2021-43798实战复现与深度利用指南
  • 零壹教育:数据挖掘的隐性偏见
  • 量化交易数据获取的终极解决方案:用efinance一站式获取股票、基金、债券、期货数据

日新闻

  • 利用微PE工具箱进行系统安装教程
  • 渗透测试十大核心工具实战指南:从信息搜集到报告生成全流程解析
  • 暗黑破坏神2存档编辑器:网页版角色修改工具完全指南

周新闻

  • Visual C++运行库修复终极指南:5分钟快速解决Windows软件启动错误
  • 手把手教你构建统计局地区经济数据爬虫:从环境搭建到数据持久化全指南
  • 2026多Agent深度解析:用AI团队替代单一模型,四种架构实战落地

月新闻

  • 【总结】入门篇:50句话让你记住架构核心概念
  • WeChatMsg技术方案解析:实现Mac微信数据自主管理的完整解决方案
  • WeChatMsg:革新性微信数据备份方案,打造你的专属数字记忆库

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号