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 graph
    ui->widget->graph(0)->setBrush(QBrush(QColor(0, 0, 255, 20))); // first graph will be filled with translucent blue
    ui->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 cosine
      y1[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对象指针,后续使用此指针或者根据索引获取指针对曲线动作。

        建议使用保存对象指针方法操作曲线,因为索引容易误操作,比如当新建两条曲线的时候,删除第一条,第二条索引会从1变成0。

//初始化返回类指针
QCPGraph *graph1 = ui->plot->addGraph();
//根据索引获取类指针
QCPGraph *graph1 = ui->plot->graph(index)

         如果你需要两条曲线在不同的坐标系,比如X轴相同,Y轴不同,那么就需要在初始化的时候指定坐标系,或者后续指定。

QCPGraph *graph1 = ui->plot->addGraph(ui->plot->xAxis,ui->plot->yAxis);
QCPGraph *graph2 = ui->plot->addGraph(ui->plot->xAxis,ui->plot->yAxis2);

//或者在addGraph之后使用
graph1->setKeyAxis(ui->plot->xAxis);
graph1->setValueAxis(ui->plot->yAxis);
graph2->setKeyAxis(ui->plot->xAxis2);
graph2->setValueAxis(ui->plot->yAxis2);

        使用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样式

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【点云分割】points3d框架学习01 —— 安装和配置

安装 $ pip install torch1.12.1cu113 torchvision0.13.1cu113 torchaudio0.12.1 --extra-index-url https://download.pytorch.org/whl/cu113 $ pip install torch-points3d $ pip install ipython $ pip install trame $ pip install h5py $ pip install gdown案例 from to…

Docker拉取并配置Grafana

Linux下安装Docker请参考&#xff1a;Linux安装Docker 安装准备 新建挂载目录 /opt/grafana/data目录&#xff0c;准备用来挂载放置grafana的数据 /opt/grafana/plugins目录&#xff0c;准备用来放置grafana的插件 /opt/grafana/config目录&#xff0c;准备用来挂载放置graf…

Python Opencv实践 - 图像直方图自适应均衡化

import cv2 as cv import numpy as np import matplotlib.pyplot as pltimg cv.imread("../SampleImages/cat.jpg", cv.IMREAD_GRAYSCALE) print(img.shape)#整幅图像做普通的直方图均衡化 img_hist_equalized cv.equalizeHist(img)#图像直方图自适应均衡化 #1. 创…

yolov5的xml文件转txt文件格式(详细解释与完整代码供应)

文章目录 前言一、yolov5训练数据格式介绍1、txt的类别对应说明2、txt的文件说明3、txt文件格式3、yolov5训练文件形式 二、xml文件读取代码解读三、xml文件转txt文件1、xml转txt代码解读2、保存txt文件代码解读 四、完整代码 前言 本文章实现xml数据格式转yolov5的txt格式&am…

ORB-SLAM2算法11之地图点MapPoint

文章目录 0 引言1 MapPoint类1.1 构造函数1.2 成员函数1.2.1 AddObservation1.2.2 EraseObservation1.2.3 SetBadFlag1.2.4 Replace1.2.5 ComputeDistinctiveDescriptors1.2.6 UpdateNormalAndDepth1.2.7 PredictScale 2 MapPoint类用途 0 引言 ORB-SLAM2算法7详细了解了Syste…

网络协议详解之STP

目录 一、STP协议&#xff08;生成树&#xff09; 1.1 生成树协议核心知识点&#xff1a; 1.2 生成树协议与导致问题&#xff1a; 生成树含义&#xff1a; 1.3 802.1D 规则&#xff1a; 802.1D 缺点&#xff1a; 1.4 PVST cisco私有 1.5 PVST 1.6 快速生成树 快速的原…

uniapp 微信小程序:RecorderManager 录音DEMO

uniapp 微信小程序&#xff1a;RecorderManager 录音DEMO 简介index.vue参考资料 简介 使用 RecorderManager 实现录音。及相关的基本操作。&#xff08;获取文件信息&#xff0c;上传文件&#xff09; 此图包含Demo中用于上传测试的服务端程序upload.exe&#xff0c;下载后用…

【Axure原型分享】能统计中英文字数的多行输入框

今天和大家分享能统计中英文字数的多行输入框的原型模板&#xff0c;在输入框里输入内容后&#xff0c;能够动态根据输入框的内容&#xff0c;统计出字符数量&#xff0c;包括总字数、中文字数、英文字数、数字字数、其他标点符号的字数&#xff0c;具体效果可以观看下方视频或…

网络安全(黑客)自学剖析

想自学网络安全&#xff08;黑客技术&#xff09;首先你得了解什么是网络安全&#xff01;什么是黑客&#xff01; 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全…

04_Redis与mysql数据双写一致性案例

04——redis与mysql数据双写一致性 一、canal 是什么 canal[ka’nel,中文翻译为水道/管道/沟渠/运河&#xff0c;主要用途是用于MySQL数据库增量日志数据的订阅、消费和解析&#xff0c;是阿里巴巴开发并开源的,采用Java语言开发&#xff1b; 历史背景是早期阿里巴巴因为杭州和…

【Python爬虫】使用代理ip进行网站爬取

前言 使用代理IP进行网站爬取可以有效地隐藏你的真实IP地址&#xff0c;让网站难以追踪你的访问行为。本文将介绍Python如何使用代理IP进行网站爬取的实现&#xff0c;包括代理IP的获取、代理IP的验证、以及如何把代理IP应用到爬虫代码中。 1. 使用代理IP的好处 在进行网站爬…

ROS通信机制之话题(Topics)的发布与订阅以及自定义消息的实现

我们知道在ROS中&#xff0c;由很多互不相干的节点组成了一个复杂的系统&#xff0c;单个的节点看起来是没起什么作用&#xff0c;但是节点之间进行了通信之后&#xff0c;相互之间能够交互信息和数据的时候&#xff0c;就变得很有意思了。 节点之间进行通信的一个常用方法就是…

SpringMVC 反射型跨站点脚本攻击

解决方案&#xff1a; 服务端校验&#xff0c;添加拦截器 配置web,xml <filter><filter-name>xssFilter </filter-name><filter-class>com.fh.filter.XssFilter </filter-class></filter> XssFilter package com.fh.filter;import com…

.NET敏捷开发框架-RDIFramework.NET V6.0发布

1、RDIFramework.NET 敏捷开发框架介绍 RDIFramework.NET敏捷开发框架&#xff0c;是我司重磅推出的基于最新.NET6与.NET Framework的快速信息化系统开发、整合框架&#xff0c;为企业快速构建跨平台、企业级的应用提供了强大支持。 开发人员不需要开发系统的基础功能和公共模…

MCU和MPU你分得清楚吗?

最近有不少同学表示在学习嵌入式的过程中分不清MCU和MPU&#xff0c;这两个确实是长得很像、容易混淆的概念&#xff0c;这里我为大家仔细分辨一下。 从概念上讲&#xff0c;MCU指的是微控制器&#xff0c;优势在于“控制”&#xff0c;MPU指的是微处理器&#xff0c;优势在于“…

微服务基础知识

文章目录 微服务基础知识一、系统架构的演变1、单体应用架构2、垂直应用架构3、分布式SOA架构&#xff08;1&#xff09;什么是SOA&#xff08;2&#xff09;SOA架构 4、微服务架构5、SOA和微服务的关系&#xff08;1&#xff09;SOA&#xff08;2&#xff09;微服务架构 二、分…

idea使用tomcat

1. 建立javaweb项目 2. /WEB-INF/web.xml项目配置文件 如果javaweb项目 先建立项目&#xff0c;然后在项目上添加框架支持&#xff0c;选择javaee 3. 项目结构 4.执行测试&#xff1a;

运维高级学习--Docker(二)

1、使用mysql:5.6和 owncloud 镜像&#xff0c;构建一个个人网盘。 #拉取mysql5.6和owncloud镜像 [rootlocalhost ~]# docker pull mysql:5.6 [rootlocalhost ~]# docker pull owncloud [rootlocalhost ~]# docker images REPOSITORY TAG IMAGE ID CREATED …

【芯片设计封装与测试】芯片测试目的、方法、分类及案例

目录 1.芯片测试概述&#xff08;目的、方法&#xff09; 1.1.测试在芯片产业价值链上的位置 2.测试如何体现在设计的过程中 2.1.半导体测试定义与基本工作机制 2.2.半导体测试环节分类及对应设备 2.3.设计验证 3.测试的各种类型 3.1.抽样测试和生产全测 3.2.测试相关…

【android12-linux-5.1】【ST芯片】HAL移植后配置文件生成报错

根据ST官方源码移植HAL源码后&#xff0c;执行readme指示中的生成配置文件指令时报错ST_HAL_ANDROID_VERSION未定义之类&#xff0c;应该是编译环境参数问题。makefile文件中是自动识别配置的&#xff0c;参数不祥就会报错&#xff0c;这里最快的解决方案是查询确定自己android…