Qt应用开发(拓展篇)——示波器/图表 QCustomPlot
一、介绍
QCustomPlot是一个用于绘图和数据可视化的Qt C++小部件。它没有进一步的依赖关系,提供友好的文档帮助。这个绘图库专注于制作好看的,出版质量的2D绘图,图形和图表,以及为实时可视化应用程序提供高性能。
QCustomPlot可以导出各种格式,如矢量化的PDF文件和光栅化的图像,如PNG, JPG和BMP。QCustomPlot是用于在应用程序中显示实时数据以及为其他媒体生成高质量图的解决方案。

二、配置
1)下载
官方网站
http://www.qcustomplot.com/
从官网下载文件,选择2.1版本以上,因为这会开始支持Qt6了。可以选择源文件+实例+说明文档全部下载,或者选择下载单动态库或纯源码,文件不大建议全部下载。

2)QtCreator配置
新建一个Qt Widgets Application工程。

把下载好的qcustomplot.h和qcustomplot.cpp放到工程下,右击项目,添加现有文件。

对话框中选择选择qcustomplot.h和qcustomplot.cpp文件添加到项目中,并在pro文件中添加Qt += printsupport。

双击mainwindows.ui进入Designer界面,新建一个widget部件。

右击widget部件,选择提升为...。

在类名称里面输入QCustomPlot,选择“添加”,然后选择“提升”。
这里要注意头文件路径,如果你是放在最外层(和pro文件同级),直接默认值就行。如果是放在某文件夹下,比如新建了一个custom文件夹并放置在里面,那么头文件这一栏应该是“custom/qcustomplot.h”。

提升之后,widget类已经被改成QCustomPlot。

在mianwindows.cpp构造函数添加如下demo代码。
// add two new graphs and set their look:ui->widget->addGraph();ui->widget->graph(0)->setPen(QPen(Qt::blue)); // line color blue for first graphui->widget->graph(0)->setBrush(QBrush(QColor(0, 0, 255, 20))); // first graph will be filled with translucent blueui->widget->addGraph();ui->widget->graph(1)->setPen(QPen(Qt::red)); // line color red for second graph// generate some points of data (y0 for first, y1 for second graph):QVector<double> x(251), y0(251), y1(251);for (int i=0; i<251; ++i){x[i] = i;y0[i] = qExp(-i/150.0)*qCos(i/10.0); // exponentially decaying cosiney1[i] = qExp(-i/150.0); // exponential envelope}// configure right and top axis to show ticks but no labels:// (see QCPAxisRect::setupFullAxesBox for a quicker method to do this)ui->widget->xAxis2->setVisible(true);ui->widget->xAxis2->setTickLabels(false);ui->widget->yAxis2->setVisible(true);ui->widget->yAxis2->setTickLabels(false);// make left and bottom axes always transfer their ranges to right and top axes:connect(ui->widget->xAxis, SIGNAL(rangeChanged(QCPRange)), ui->widget->xAxis2, SLOT(setRange(QCPRange)));connect(ui->widget->yAxis, SIGNAL(rangeChanged(QCPRange)), ui->widget->yAxis2, SLOT(setRange(QCPRange)));// pass data points to graphs:ui->widget->graph(0)->setData(x, y0);ui->widget->graph(1)->setData(x, y1);// let the ranges scale themselves so graph 0 fits perfectly in the visible area:ui->widget->graph(0)->rescaleAxes();// same thing for graph 1, but only enlarge ranges (in case graph 1 is smaller than graph 0):ui->widget->graph(1)->rescaleAxes(true);// Note: we could have also just called ui->widget->rescaleAxes(); instead// Allow user to drag axis ranges with mouse, zoom with mouse wheel and select graphs by clicking:ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
编译构建项目成功后,执行即可看到demo图表。

3)添加说明文档
下载的文档可以直接添加到QtCreator的帮助里面。

把文件放到 D:\Qt\Qt5.9.6\Tools\QtCreator\share\doc\qtcreator底下

QtCreator选择工具-选项。

选择-文档-添加,在弹出的界面选择把qcustomplot.qch文件加进来。

如此,我们在帮助界面搜索qcustomplot就可以直接浏览帮助文档。 
三、常用功能详解
1)曲线
使用addGraph()方法新建曲线,返回一个QCPGraph对象指针,后续使用此指针或者根据新建的顺序传入索引ui->widget->graph(index)对曲线动作。
建议使用保存对象指针方法操作曲线,因为索引不直观。而且当新建两条曲线的时候,删除第一条,第二条索引会从1变成0,会有误操作的风险。
QCPGraph *graph1 = ui->plot->addGraph();
使用setData()方法设置曲线坐标数据,坐标数据使用QVector封装,使用此方法会覆盖原先的曲线。注意这里x和y的动态数组长度要一致,否则控制台会报错并失效。
QVector<double> x0(251), y0(251);
for (int i=0; i<251; ++i)
{x[i] = i;y0[i] = qExp(-i/150.0)*qCos(i/10.0);
}
ui->plot->graph(0)->setData(x0,y0);//写入数据
使用addData()方法在原先基础上添加数据,适用于动态曲线,当然如果一直重新setData也是可以,不建议这么做。
ui->plot->graph(0)->addData(x0, y0)
使用clear()清空数据,但是曲线还保留着。
ui->plot->graph(0)->data()->clear();
使用setName()方法设置曲线名称,name方法返回曲线名称。
ui->plot->graph(0)->setName(QString("graph1"));
qDebug()<<ui->Plot->graph(0)->name();
使用removeGraph()方法传入QCPGraph指针或者索引移除曲线。
ui->plot->removeGraph(0);
ui->plot->removeGraph(graph1);
设置曲线画笔颜色、宽度、样式。
ui->plot->graph(0)->setPen(QPen(QColor(120, 120, 120), 2));
设置曲线使用刷子。
ui->plot->graph(1)->setBrush(QColor(200, 200, 200, 20));

使用setChannelFillGraph()把通道2包含在1里面,这样刷子颜色就不会透视。
QCPGraph *graph2 = ui->widget->addGraph();
graph2->setData(x2, y2);
graph2->setPen(Qt::NoPen);
graph2->setBrush(QColor(200, 200, 200, 20));
graph2->setChannelFillGraph(graph1);

使用setScatterStyle()设置曲线散点的样式。
ui->plot->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, QPen(Qt::black, 1.5), QBrush(Qt::white), 9));

2)柱状图
实例化QCPBars()。
QCPBars *bars1 = new QCPBars(ui->widget->xAxis, ui->widget->yAxis);
使用setWidth()设置柱状图宽度
bars1->setWidth(10);
使用setPen()设置画笔
bars1->setPen(QPen(QColor(120, 120, 120), 2));
使用setBrush()设置刷子颜色填充。
bars1->setBrush(QColor(10, 140, 70, 160));
使用moveAbove()设置栏2在1的上方。
bars2->moveAbove(bars1);

3)坐标轴

使用setVisible()方法设置是否显示。
ui->plot->xAxis2->setVisible(true);
ui->plot->yAxis2->setVisible(true);
使用setTickLabels()方法设置是否显示刻度。
ui->widget->xAxis2->setTickLabels(false);
ui->widget->yAxis2->setTickLabels(false);
使用rescaleAxes()方法设置自适应坐标轴,防止因为坐标轴范围过长而出现大量无数据地带
ui->Plot->graph(0)->rescaleAxes();
使用setRange()设置坐标轴范围,使用range()获取坐标轴范围数值。
ui->plot->xAxis->setRange(0, 100);
ui->plot->yAxis->setRange(0, 100);
QCPRange XAxis_Range=ui->plot->xAxis->range();
缩放、自适应等会触发rangeChanged()信号,同步使用setRange(),保证上下、左右坐标一致。
connect(ui->plot->xAxis, SIGNAL(rangeChanged(QCPRange)), ui->plot->xAxis2, SLOT(setRange(QCPRange)));
connect(ui->plot->yAxis, SIGNAL(rangeChanged(QCPRange)), ui->plot->yAxis2, SLOT(setRange(QCPRange)));
3)样式
使用setTickLabelColor()设置坐标轴标签的颜色。
ui->plot->xAxis->setTickLabelColor(Qt::red);
ui->plot->yAxis->setTickLabelColor(Qt::red);
使用setTickPen()设置含标签的刻度的画笔的颜色、线宽和样式。
ui->widget->xAxis->setTickPen(QPen(Qt::red, 1));
ui->widget->yAxis->setTickPen(QPen(Qt::red, 1));
使用setSubTickPen()设置不含标签的刻度的画笔的颜色、线宽和样式。
ui->widget->xAxis->setSubTickPen(QPen(Qt::red, 1));
ui->widget->yAxis->setSubTickPen(QPen(Qt::red, 1));
使用setBasePen()设置坐标轴画笔的颜色、线宽和样式。
ui->plot->xAxis->setBasePen(QPen(Qt::red, 1));
ui->plot->yAxis->setBasePen(QPen(Qt::red, 1));
使用setSubGridVisible()设置是否显示二级网格。
ui->plot->xAxis->grid()->setSubGridVisible(true);
ui->plot->yAxis->grid()->setSubGridVisible(true);

使用setPen()设置网格的画笔的颜色、线宽和样式。
ui->plot->xAxis->grid()->setPen(QPen(QColor(140, 140, 140), 1, Qt::DotLine));
ui->plot->yAxis->grid()->setPen(QPen(QColor(140, 140, 140), 1, Qt::DotLine));
使用setSubGridPen()设置二级网格的画笔的颜色、线宽和样式。
ui->plot->xAxis->grid()->setSubGridPen(QPen(QColor(80, 80, 80), 1, Qt::DotLine));
ui->plot->yAxis->grid()->setSubGridPen(QPen(QColor(80, 80, 80), 1, Qt::DotLine));
使用setZeroLinePen()设置零线的画笔的颜色、线宽和样式。
ui->plot->xAxis->grid()->setZeroLinePen(Qt::NoPen);
ui->plot->yAxis->grid()->setZeroLinePen(Qt::NoPen);
使用setBackground()设置背景颜色,设置渐变色,也可以直接使用图片,纯色刷子来当背景。
QLinearGradient plotGradient;
plotGradient.setStart(0, 0);
plotGradient.setFinalStop(0, 350);
plotGradient.setColorAt(0, QColor(80, 80, 80));
plotGradient.setColorAt(1, QColor(50, 50, 50));
ui->plot->setBackground(plotGradient);QLinearGradient axisRectGradient;
axisRectGradient.setStart(0, 0);
axisRectGradient.setFinalStop(0, 350);
axisRectGradient.setColorAt(0, QColor(80, 80, 80));
axisRectGradient.setColorAt(1, QColor(30, 30, 30));
ui->widget->axisRect()->setBackground(axisRectGradient);
使用setUpperEnding()设置上轴结束的样式。
ui->plot->xAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);
ui->plot->yAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);
4)图例

使用setVisible()设置图例是否显示。
ui->plot->legend->setVisible(true);
使用setFillOrder()设置图例信息的水平方向。
ui->plot->legend->setFillOrder(QCPLayoutGrid::foColumnsFirst);

使用addElement()设置图例显示的坐标、位置和比例。
ui->plot->plotLayout()->addElement(1 , 0, ui->plot->legend);

使用setBorderPen()设置图例边框颜色、线宽、样式。
ui->plot->legend->setBorderPen(QPen(QColor(140, 140, 140), 1, Qt::DotLine));
使用setRowStretchFactor()设置显示比例,图例所在框的大小。
ui->plot->plotLayout()->setRowStretchFactor(1, 0.001);
4)其他
使用setInteractions()方法设置交互策略
ui->Plot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
//放大拖拽选中等枚举
enum Interaction { iRangeDrag = 0x001 //左键点击可拖动,iRangeZoom = 0x002 //范围可通过鼠标滚轮缩放,iMultiSelect = 0x004 //可选中多条曲线,iSelectPlottables = 0x008 //线条可选中,iSelectAxes = 0x010 //坐标轴可选,iSelectLegend = 0x020 //图例是可选择的,iSelectItems = 0x040 //可选择项(矩形、箭头、文本项等,iSelectOther = 0x080 //所有其他对象都是可选的};
使用replot()重新启动绘制,当你需要一条动态曲线的时候,除了动态的addData(),还需要不断的使用replot()进行后续的绘制。
ui->plot->replot();
保存成Pdf、Png、Jpg、Bmp格式文件。
bool savePdf (const QString &fileName, int width=0, int height=0, QCP::ExportPen exportPen=QCP::epAllowCosmetic, const QString &pdfCreator=QString(), const QString &pdfTitle=QString())bool savePng (const QString &fileName, int width=0, int height=0, double scale=1.0, int quality=-1, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch)bool saveJpg (const QString &fileName, int width=0, int height=0, double scale=1.0, int quality=-1, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch)bool saveBmp (const QString &fileName, int width=0, int height=0, double scale=1.0, int resolution=96, QCP::ResolutionUnit resolutionUnit=QCP::ruDotsPerInch)

QPen样式

相关文章:
Qt应用开发(拓展篇)——示波器/图表 QCustomPlot
一、介绍 QCustomPlot是一个用于绘图和数据可视化的Qt C小部件。它没有进一步的依赖关系,提供友好的文档帮助。这个绘图库专注于制作好看的,出版质量的2D绘图,图形和图表,以及为实时可视化应用程序提供高性能。 QCustomPl…...
【精度丢失】后端接口返回的Long类型参数,不同浏览器解析出的结果不一样
1、业务背景 有个同事找我帮他看一个问题,他给前端提供了一个接口。 这个接口是用来反查id的,他这里这个参数正常的返回值应该是 283232039247028226。 但前端反馈他,前端在浏览器(火狐)获取的值是 283232039247028…...
2023年国赛 高教社杯数学建模思路 - 案例:感知机原理剖析及实现
文章目录 1 感知机的直观理解2 感知机的数学角度3 代码实现 4 建模资料 # 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 感知机的直观理解 感知机应该属于机器学习算法中最简单的一种算法,其…...
java-红黑树
节点内部存储 红黑树规则 或者: 红黑树添加节点规则: 添加节点默认是红色的(效率高) 红黑树示例 注:红黑树增删改查性能都很好...
vue2 vue中的常用指令
一、为什么要学习Vue 1.前端必备技能 2.岗位多,绝大互联网公司都在使用Vue 3.提高开发效率 4.高薪必备技能(Vue2Vue3) 二、什么是Vue 概念:Vue (读音 /vjuː/,类似于 view) 是一套 **构建用户界面 ** 的 渐进式 …...
AI驱动下的智能制造:工业自动化的新纪元
随着人工智能(AI)技术的持续进步,其在工业自动化领域的影响日益显著。作为现代科技的代表,AI不仅为各行业带来了前所未有的商机和技术思路,更在工业自动化领域中引发了一场深刻的变革。本文将深入探讨AI对智能制造的影…...
docker 命令
一、docker命令 1、镜像保存 docker save imageid -o modelzoozl.tar #把镜像保存到本地 docker load -i dockername #把tar包load下来,load成镜像 docker export CONTAINERID/CONTAINERNAME -o modelzoozl.tar #把启动着的镜像导出 docker import modelzo…...
2023年高教社杯数学建模思路 - 复盘:光照强度计算的优化模型
文章目录 0 赛题思路1 问题要求2 假设约定3 符号约定4 建立模型5 模型求解6 实现代码 建模资料 0 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 1 问题要求 现在已知一个教室长为15米,宽为12米&…...
生成式人工智能的潜在有害影响与未来之路(二)
利润高于隐私:不透明数据收集增加 背景和风险 生成型人工智能工具建立在各种大型、复杂的机器学习模型之上,这些模型需要大量的训练数据才能发挥作用。对于像ChatGPT这样的工具,数据包括从互联网上抓取的文本。对于像Lensa或Stable Diffusi…...
如何自己实现一个丝滑的流程图绘制工具(三)自定义挂载vue组件
背景 bpmn-js是个流程图绘制的工具,但是现在我希望实现的是,绘制的不是节点而是一个vue组件。 保留线的拖拽和连接。 方案 那就说明不是依赖于节点的样式,找到了他有个属性,就是类似覆盖节点的操作。 思路就是用vue组件做遮罩&…...
UNIAPP调用API接口
API:开发者可以通过这些接口与其它程序进行交互,获取所需数据或者执行指定操作。 网络请求 API: UniApp 中内置了网络请求 API,方便调用 uni.request uni.uploadFile uni.request 接口主要用于实现网络请求。GET 和 POST 是使用最普遍的两种…...
理解 Delphi 的类(五) - 认识类的继承
先新建一个 VCL Forms Application 工程, 代码中就已经出现了两个类: 一个是 TForm 类; 一个是 TForm1 类; TForm1 继承于 TForm. TForm 是 TForm1 的父类; TForm1 是 TForm 的子类. unit Unit1;interfaceusesWindows, Messages, SysUtils, Variants, Classes, Graphics, Contr…...
mybatis概述及搭建
目录 1.概述 2.mybatis搭建 1.创建一个maven项目,添加mybatis、mysql所依赖的jar 2.创建一个数据库表,及对应的java类 3.创建一个mybatis的核心配置文件,配置数据库连接信息,配置sql映射文件 4.创建sql映射文件,…...
DNDC模型---土壤碳储量、温室气体排放、农田减排、土地变化、气候变化中的应用
由于全球变暖、大气中温室气体浓度逐年增加等问题的出现,“双碳”行动特别是碳中和已经在世界范围形成广泛影响。国家领导人在多次重要会议上讲到,要把“双碳”纳入经济社会发展和生态文明建设整体布局。同时,提到要把减污降碳协同增效作为促…...
Android studio 2022.3.1 鼠标移动时不显示快速文档
在使用技术工具的过程中,我们时常会遇到各种各样的问题和挑战。最近,我升级了我的Android Studio到2022.3.1版本,但是在使用过程中,我碰到了一个让我颇为困扰的问题:在鼠标移动到类名或字段上时,原本应该显…...
五度易链最新“产业大数据服务解决方案”亮相,打造数据引擎,构建智慧产业!
快来五度易链官网 点击网址【http://www.wdsk.net/】 看看我们都发布了哪些新功能!!! 自2015年布局产业大数据服务行业以来,“五度易链”作为全国产业大数据服务行业先锋企业,以“让数据引领决策,以智慧驾驭未来”为愿景,肩负“打…...
简述hive环境搭建
文章目录 部署参数配置hive简单命令 部署 Hive的三种部署模式,主要按Metastore 的运行模式进行区分。 在安装Hive之前,要求先预装JDK 8、Hadoop、MySQL ; 1.下载hive,并解压缩到用户主目录下 tar -xzvf apache-hive-2.3.6-bin.t…...
小米AI音箱联网升级折腾记录(解决配网失败+升级失败等问题)
小米AI音箱(一代)联网升级折腾记录 我折腾了半天终于勉强能进入下载升级包这步,算是成功一半吧… 总结就是,网络信号一定要好,需要不停换网找到兼容的网,还需要仔细配置DNS让音响连的上api.mina.mi.com 推荐…...
tensorRT安装
官方指导文档:Installation Guide :: NVIDIA Deep Learning TensorRT Documentation 适配很重要!!!! 需要cuda, cuDNN, tensorRT三者匹配。我的cuda11.3 所以对应的cuDNN和tensorRT下载的是如下版本: cud…...
电脑重装+提升网速
https://www.douyin.com/user/self?modal_id7147216653720341767&showTabfavorite_collectionhttps://www.douyin.com/user/self?modal_id7147216653720341767&showTabfavorite_collection 零封有哈数的主页 - 抖音 (douyin.com)https://www.douyin.com/user/self?…...
eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
Map相关知识
数据结构 二叉树 二叉树,顾名思义,每个节点最多有两个“叉”,也就是两个子节点,分别是左子 节点和右子节点。不过,二叉树并不要求每个节点都有两个子节点,有的节点只 有左子节点,有的节点只有…...
GC1808高性能24位立体声音频ADC芯片解析
1. 芯片概述 GC1808是一款24位立体声音频模数转换器(ADC),支持8kHz~96kHz采样率,集成Δ-Σ调制器、数字抗混叠滤波器和高通滤波器,适用于高保真音频采集场景。 2. 核心特性 高精度:24位分辨率,…...
Scrapy-Redis分布式爬虫架构的可扩展性与容错性增强:基于微服务与容器化的解决方案
在大数据时代,海量数据的采集与处理成为企业和研究机构获取信息的关键环节。Scrapy-Redis作为一种经典的分布式爬虫架构,在处理大规模数据抓取任务时展现出强大的能力。然而,随着业务规模的不断扩大和数据抓取需求的日益复杂,传统…...
AI语音助手的Python实现
引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...

