Qt QCustomPlot 入门教程
简述
QCustPlot是一个基于Qt C++的图形库,用于绘制和数据可视化 制作漂亮的2D图 曲线图、趋势图、坐标图、柱状图等,并为实时可视化应用程序提供高性能服务。它没有进一步的依赖关系,并有着良好的文档记录。
QCustPlot可以导出为各种格式,比如:PDF文件和位图(如:PNG、JPG、BMP)。
可在自己的项目中直接使用两个源文件(qcustplot.h与qcustplotpp),或预先编译成库。
下载、配置和使用
下载
QCustPlot首页:qcustplot/
进入QCustPlot下载页,下载最新的完整包(包含:源码、文档、示例)!
将下载好的安装包进行解压缩,里面包含文档、示例、更改日志、GPL授权、以及最重要的两个文件qcustplot.h与qcustplotpp。
配置
完整的API文档在cplete API documentation上面,或者作为完整包的一部分,在解压缩后的目录中可以找到。里面包含一个HTML文档的层次结构和qch帮助文件用于QtCreator/Assistant集成。如果使用QtCreator或Assistant,应考虑使用qch文件,这将极大地提高工作效率!
集成到QtCreator/Assistant
集成qch文件相当简单:
- 复制qcustplot.qch文件到你需要存储的地方(例如:本地QtCreator配置目录)。
- 在QtCreator中,选择:工具 > 选项 > 帮助 > 文档,你会看到一个加载文档模块的列表,以及添加/删除模块的按钮。点击”添加…”按钮,选择qcustplot.qch文件。
这样,我们就添加完成了。可以通过:帮助 > 索引,来搜索QCustPlot相关的类或函数。
当你把光标放在任何QCustPlot相关的类或函数上时,按下F1键,就会有相应的文档项弹出,就像Qt组件一样。
使用
在examples中我们会看到一些自带的示例,可以运行看一下效果。
如果在自己的项目中使用,需要进行以下配置:
首先,在pro中需要添加(由于QCustPlot中存在导出功能,使用了printsupport模块):
QT += printsupport然后,将qcustplot.h与qcustplotpp拷贝到工程目录下,右键 > 添加现有文件…,将这两个文件添加至工程。
在调用qcustplot的地方,需要引入:
#include "qcustplot.h"创建一个qcustplot对象。
QCustPlot *pCustPlot = new QCustPlot(this);QCustPlot类
几个重要的类
- QCustPlot图标类:用于图标的显示和交互
- QCPLayer图层:管理图层元素(QCPLayerable),所有可显示的对象都是继承自图层元素。
- QCPAbstractPlottable绘图元素:包含折线图(QCPGraph)、曲线图(QCPCurve)、柱状图(QCPBars)、QCPStatiBox(盒子图)、QCPColorMap(色谱图)、QCPFinancial(金融图)
- QCPAxisRect坐标轴矩形:一个坐标轴矩形默认包含上下左右四个坐标,但是可以添加多个坐标轴。
QCustPlot类管理着所有图层,它本身自带6个图层,分别是:
- 背景图(background)
- 网格层(grid)
- 绘图层(main)
- 坐标轴层(axis)
- 图例层(legend)
- overlay层(overlay)
依据层的顺序不同,绘制的顺序也不同,越在底下的层越早绘制,当前层默认为绘图层main。
我们一般操作的都在绘图层,绘图层则在QCPAxisRect中,QCustPlot类默认包含一个QCPAxisRect。下图中可以看到一个QCPAxisRect一般包含4个轴。
个性化外观
设置QCustPlot的背景颜色
1 QLinearGradient plotGradient; 2 plotGradient.setStart(0, 0); 3 plotGradient.setFinalStop(0, 350); 4 plotGradient.setColorAt(0, QColor(80, 80, 80)); 5 plotGradient.setColorAt(1, QColor(50, 50, 50)); 6 custPlot>setBackground(plotGradient); // 设置背景颜色设置QCPAxisRect轴矩阵的背景颜色
1 QLinearGradient axisRectGradient; 2 axisRectGradient.setStart(0, 0); 3 axisRectGradient.setFinalStop(0, 350); 4 axisRectGradient.setColorAt(0, QColor(80, 80, 80)); 5 axisRectGradient.setColorAt(1, QColor(30, 30, 30)); 6 /* 设置QCPAxisRect背景颜色 */ 7 custPlot>axisRect()>setBackground(axisRectGradient);设置QCPGrid网格的风格
1 /* 每条网格对应一个刻度 */ 2 /* 网格线(对应刻度)画笔 */ 3 custPlot>xAxis>grid()>setPen(QPen(QColor(140, 140, 140), 1, Qt::DotLine)); 4 custPlot>yAxis>grid()>setPen(QPen(QColor(140, 140, 140), 1, Qt::DotLine)); 5 /* 子网格线(对应子刻度)画笔 */ 6 custPlot>xAxis>grid()>setSubGridPen(QPen(QColor(80, 80, 80), 1, Qt::DotLine)); 7 custPlot>yAxis>grid()>setSubGridPen(QPen(QColor(80, 80, 80), 1, Qt::DotLine)); 8 /* 显示子网格线 */ 9 custPlot>xAxis>grid()>setSubGridVisible(true); 10 custPlot>yAxis>grid()>setSubGridVisible(true); 11 /* 设置刻度为0时的网格线的画笔 */ 12 custPlot>xAxis>grid()>setZeroLinePen(QPen(Qt::red)); 13 custPlot>yAxis>grid()>setZeroLinePen(QPen(Qt::red));图表的风格
1 QPen pen; 2 QStringList lineNames; 3 lineNames << "lsNone" << "lsLine" << "lsStepLeft" << "lsStepRight" << "lsStepCenter" << "lsImpulse"; 4 for (int i = QCPGraph::lsNone; i <= QCPGraph::lsImpulse; ++i) 5 21 custPlot>graph()>setData(x, y); 22 custPlot>graph()>rescaleAxes(true); 23 }图表画刷
1 /* 第一种:与0刻度线围成区域 */ 2 custPlot>addGraph(); 3 custPlot>graph(0)>setPen(QPen(Qt::blue)); 4 custPlot>graph(0)>setBrush(QBrush(QColor(0, 0, 255, 20))); 5 custPlot>addGraph(); 6 custPlot>graph(1)>setPen(QPen(Qt::red)); 7 /* 第二种方式:与其它图围成区域,使用的是图0的画刷 */ 8 custPlot>graph(0)>setChannelFillGraph(custPlot>graph(1)); 9 /* 将图0与图1围成区域 */QCPAxis坐标系
QCPAxis有四个成员变量,分别代表四个坐标轴:xAxis(下)、yAxis(左)、xAxis2(上)、yAxis2(右)。
坐标轴
默认只显示左y轴和下边的x轴,调用setVisible(bool)设置轴是否显示。
1 custplot>yAxis2>setVisible(true);//显示y轴2 2 custplot>xAxis2>setVisible(true);//显示x轴2也可以设置一个完整的坐标Box,会直接显示四个轴。
custplot>axisRect()>setupFullAxesBox();//四边安装轴并显示设置刻度
提供了设置坐标轴刻度、间距、范围等函数
1 /* 设置坐标轴刻度间距 */ 2 setTickStep(double step); 3 /* 设置坐标轴刻度表(将坐标轴刻度设置为vec) */ 4 setTickVector(const QVector<double> &vec); 5 /* 一般刻度数量是自动调整的,但也可以手动设置,例如100到100默认5个主刻度 */ 6 /* 可以设置成11个主刻度,注意有个刻度步进策略,如果默认是tssReadability, 7 那么custplot有时仍会自动调整,使刻度便于阅读 */ 8 custplot>xAxis>ticker()>setTickCount(11);//11个主刻度 9 custplot>xAxis>ticker()>setTickStepStrategy(QCPAxisTicker::tssReadability); 10 //可读性优于设置设置标签
1 custPlot>xAxis>setLabel("x"); 2 custPlot>yAxis>setLabel("y"); 3 custplot>xAxis>setTickLabels(true);//显示刻度值 4 custplot>xAxis>setTickLabelSide(QCPAxis::LabelSide::lsInside);//显示在内部 5 /* 设置标签旋转角度(顺时针) */ 6 custPlot>xAxis>setTickLabelRotation(30);设置范围
1 custPlot>xAxis>setRange(1, 1); 2 custPlot>yAxis>setRange(0, 1);设置画笔
1 /* 轴线的画笔 */ 2 custPlot>xAxis>setBasePen(QPen(Qt::white, 1)); 3 /* 轴刻度线的画笔 */ 4 custPlot>xAxis>setTickPen(QPen(Qt::white, 1)); 5 /* 轴子刻度线的画笔 */ 6 custPlot>xAxis>setSubTickPen(QPen(Qt::white, 1));设置label字体颜色
1 /* 轴刻度文字颜色 */ 2 custPlot>xAxis>setTickLabelColor(Qt::white); 3 /* 轴标签颜色 */ 4 custPlot>xAxis>setLabelColor(Qt::white);设置刻度长度
1 /* 轴线内刻度的长度 */ 2 custPlot>xAxis>setTickLengthIn(3); 3 /* 轴线外刻度的长度 */ 4 custPlot>xAxis>setTickLengthOut(5); 5 custplot>xAxis>setSubTickLengthIn(15);//子刻度向内延伸15 6 custplot>xAxis>setSubTickLengthOut(5);//子刻度向外延伸5设置坐标轴线形状
1 /* 设置轴线结束时的风格为 实角三角形但内部有凹陷的形状,setLowerEnding设置轴线开始时的风格 */ 2 custPlot>xAxis>setUpperEnding(QCPLineEnding::esSpikeArrow); 3 custplot>xAxis>setUpperEnding(QCPLineEnding::esSpikeArrow);//x轴终点箭头图案 4 custplot>xAxis>setLowerEnding(QCPLineEnding::esDisc);//x轴起点圆点图案 5 custplot>yAxis>setUpperEnding(QCPLineEnding::esSquare);//y轴终点小方块图案设置刻度原点
有些需求要修改刻度显示的原点,例如原来是10,5,0,5,10,15,设置原点为1后变成14,9,4,1,6,11,代码例子:
设置坐标轴位置
设置离外部和内部各50,代码例子:
设置上下轴、左右轴范围同步
利用rangeChanged信号传递轴范围QCPRange,范围改变时将xAxis的范围传给xAxis2,yAxis也是,就能实现轴范围同步了。
设置坐标轴为时间格式
1 QSharedPointer<QCPAxisTickerDateTime> dateTick(new QCPAxisTickerDateTime); 2 dateTick>setDateTimeFormat("yyyyMMdd hh:mm:ss:zzz"); 3 custPlot>xAxis>setTicker(dateTick);网格
设置画笔
设置子网络线
1 /* 显示子网格线 */ 2 custPlot>xAxis>grid()>setSubGridVisible(true); 3 custPlot>yAxis>grid()>setSubGridVisible(true);背景
设置背景
设置背景属性
1 custplot>axisRect()>setBackgroundScaled(true);//启用背景缩放 2 custplot>axisRect()>setBackgroundScaledMode(Qt::AspectRatioMode::IgnoreAspectRatio);//自由缩放缩放模式类型和效果
其他设置
设置自动调整范围
设置自动调整范围后,可以使全部数据可见。调用rescaleAxes (bool onlyEnlarge = false)函数,将重新调整与此绘图表关联的键和值轴,以显示所有的数据。
onlyEnlarge 默认false,表示范围可以缩小放大,如果为true表示只能放大,而不会缩小范围。
因为如果有多个曲线,第一个曲线调用rescaleAxes ()函数后,整个坐标轴的范围被缩小,曲线正好占满整个区域,但是如果其他曲线再次调用了rescaleAxes ()函数,如果范围缩小就可能导致数据无法显示,所以后面的曲线要设置参数为true,区域不会被缩小。最终能显示所有曲线的数据。
1 // 让范围自行缩放,使图0完全适合于可见区域: 2 custPlot>graph(0)>rescaleAxes(); 3 // 图1也是一样自动调整范围,但只是放大或不变范围 4 custPlot>graph(1)>rescaleAxes(true); 5 // 图2也是一样自动调整范围,但只是放大或不变范围 6 custPlot>graph(2)>rescaleAxes(true); 7 // 图3也是一样自动调整范围,但只是放大或不变范围 8 custPlot>graph(2)>rescaleAxes(true);设置坐标轴缩放比例
QCustPlot模式对坐标系的x轴和y轴都是一起缩放的,用时候用起来不方便,有时候需要单独对x轴或者y轴进行缩放。
方法1:修改缩放比例
QCustPlot给我们提供了setRangeZoFactor()函数,设置区域放大因子。这样就可以实现单个轴放大缩小比例。
ui>custPlot>axisRect()>setRangeZoFactor(1.2,1);//x方向为1.2 y为1 是不改变。方法2:QCustPlot自己提供的函数设置
1 void MainWindow::wheelEvent(QWheelEvent *event) 2 11 else if (ui>custPlot>yAxis>selectedParts().testFlag(QCPAxis::spAxis)) 12 16 else 17 ui>custPlot>axisRect()>setRangeZo(Qt::Horizontal|Qt::Vertical); 18 }设置坐标系的操作属性
1 //设置基本坐标轴(左侧Y轴和下方X轴)可拖动、可缩放、曲线可选、legend可选、设置伸缩比例,使所有图例可见 2 CustPlot>setInteractions(QCP::iRangeDrag|QCP::iRangeZo| QCP::iSelectAxes | 3 QCP::iSelectLegend | QCP::iSelectPlottables);画图类
QCustPlot 提供了多个画图类
QCPCurve:与QCPGraph 类似,差别在于它是用于展示参数化曲线,可以有循环。
QCPBars:柱形图,如果有多个QCPBars ,可以依次重叠。
QCPStatisticalBox、QCPColorMap、QCPFinancial。与QCPGraph 不同的是,这些画图类在添加到QCustPlot 的时候需要使用new创建一个实例,而不能直接。
QCPGraph类
添加曲线
每一条曲线相当于一个图层,需要调用qcustplot来添加。
给曲线添加数据
添加图层后,可以用qcustplot的graph(编号)来获取图层对象,或者直接拿到图层指针。编号按照添加的顺序寻址。
设置图层名称
custPlot>graph(0)>setName("第一个示例"); // 设置曲线图的名字设置图层(曲线)画笔
QCPGraph::setPen(const QPen &pen);设置图层(曲线)风格
QCPGraph::setLineStyle(LineStyle ls);设置曲线形状
曲线形状有“*、+、x、o”等
设置曲线填充方式
给graph设置brush后,会自动填充曲线和x轴之间的空间。
如果想设置两条曲线之间填充的颜色
/* 设置与某之间曲线填充 */ QCPGraph::setChannelFillGraph(otherGraph);图例
显示图例
添加完数据,记得重画图像
custPlot>replot();1 #include "qcustplot.h" MainWindow::MainWindow(QWidget *parent) : CustWindow(parent) 2 12 // 向绘图区域QCustPlot添加一条曲线 13 QCPGraph *pGraph = pCustPlot>addGraph(); 14 // 添加数据 15 pCustPlot>graph(0)>setData(x, y); 16 // 设置坐标轴名称 17 pCustPlot>xAxis>setLabel("x"); 18 pCustPlot>yAxis>setLabel("y"); 19 // 设置背景色 20 pCustPlot>setBackground(QColor(50, 50, 50)); 21 pGraph>setPen(QPen(QColor(32, 178, 170))); 22 // 设置x/y轴文本色、轴线色、字体等 23 pCustPlot>xAxis>setTickLabelColor(Qt::white); 24 pCustPlot>xAxis>setLabelColor(QColor(0, 160, 230)); 25 pCustPlot>xAxis>setBasePen(QPen(QColor(32, 178, 170))); 26 pCustPlot>xAxis>setTickPen(QPen(QColor(128, 0, 255))); 27 pCustPlot>xAxis>setSubTickPen(QColor(255, 165, 0)); 28 QFont xFont = pCustPlot>xAxis>labelFont(); 29 xFont.setPixelSize(20); 30 pCustPlot>xAxis>setLabelFont(xFont); 31 pCustPlot>yAxis>setTickLabelColor(Qt::white); 32 pCustPlot>yAxis>setLabelColor(QColor(0, 160, 230)); 33 pCustPlot>yAxis>setBasePen(QPen(QColor(32, 178, 170))); 34 pCustPlot>yAxis>setTickPen(QPen(QColor(128, 0, 255))); 35 pCustPlot>yAxis>setSubTickPen(QColor(255, 165, 0)); 36 QFont yFont = pCustPlot>yAxis>labelFont(); 37 yFont.setPixelSize(20); 38 pCustPlot>yAxis>setLabelFont(yFont); 39 // 设置坐标轴显示范围,否则只能看到默认范围 40 pCustPlot>xAxis>setRange(11, 11); 41 pCustPlot>yAxis>setRange(1100, 1100); 42 ... 43 }
如果需要导出,我们可以调用对应的save…接口。
例如,导出一张为PNG格式,宽度、宽度分别为px、300px的图片:
pCustPlot>savePng("custPlot.png", , 300);QCPGraph
用这个类来添加一个图层
1 /* 增加图层 */ 2 QCPGraph *graphTemp = pCustPlot>addGraph(); 3 /* 设置画笔 */ 4 graphTemp>setPen(QPen(Qt::red)); 5 /* 设置画刷,曲线和x轴围成的面积颜色 */ 6 graphTemp>setBrush(QBrush(QColor(100,0,205,50))); 7 graphTemp>setAntialiasedFill(false); 8 // 设置图层反锯齿:关闭 9 graphTemp>setLineStyle(QCPGraph::lsLine); 10 graphTemp>setScatterStyle(QCPScatterStyle::ssDisc); 11 // 设置点的形状 12 /* 设置图层名称 */ 13 graphTemp>setName("实时电流曲线"); 14 /* 传入数据,数据类型为double */ 15 graphTemp>setData(x, y);方案解决
实现横坐标为日期时间
因为曲线轴设置的坐标只能为double型数据,需要将时间转换为double。就需要我们将字符串型的时间数据转换为double型的秒数。需要先将字符串转换为QDateTime,然后再使用totime_t()转换成距离1970年的秒数储存到数组。
上一篇:CODESYS 仿真运行
Qt