大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE稳定放心使用
日常记录学习QCustomPlot的配置和编码过程。
1.结构
QCustomPlot类的命名规则是QCP加xxx。类的组织有很强的区分性,就如图Qt中的模块分类。
Class |
Name |
QCPPlotTitle |
图表标题 |
QCPAxis |
坐标轴、上下左右四个坐标轴 |
QCPGrid |
网格线 |
QCPLegend |
图例 |
QCPGraph |
折线图 |
QCPCurve |
曲线图,可有循环、同一x可有多个y值 |
QCPBars |
柱形图,多个可依次重叠 |
QCPStatisticalBox |
盒子图(需实例化)、统计学箱 |
QCPColorMap |
色谱图(实例化) |
QCPFinancial |
金融图(实例化) |
QCPAbstractItem |
标示项 |
QCPItemStraightLine |
直线 |
QCPItemLine |
线段 |
QCPItemCurve |
曲线 |
QCPItemRect |
矩形 |
QCPItemEllipse |
椭圆 |
QCPItemText |
文本 |
QCPItemTracer |
小圆球 |
QCPItemPixmap |
图片 |
QCPItemBracket |
括弧 |
QCPAxisRect |
坐标轴矩形,用于存放轴 |
表1 QcustomPlot模块分类表
这里并没有全部列出,可以参看如下结构图,详细类继承结构链接:
https://www.qcustomplot.com/documentation/inherits.html
下图中最左边的QCPLayerable意思为“可分层的对象”,分层意味着对象绘制方式是有层次的,可以调整各对象的所在层,进而让一些对象显示在最上层等。所有可绘制到屏幕上的对象,都是它的派生类。
图1 函数QCPLayerable继承结构图
QCPAbstractItem是抽象类“项”,不可直接使用,继承自它的类用于显示一些特殊的图形,比如放上一张图片(QCPItemPixmap)或文字(QCPItemText ),一个可加入箭头的直线(QCPItemLine)等等。
QCPAbstractPlottable 是抽象类“可绘制的图”,继承自它的类,就是可以用于表示数据系列的图线了。比如QCPBars(柱状图) 、QCPColorMap(色图)、QCPGraph(曲线) 、QCPCurve(弧线) 、QCPStatisticalBox (统计学箱)的对应图例如下:
图2五种可绘制曲线图示例
QCPLayoutElement 为可布局元素。继承自它的类,都可以通过QCP布局系统,按照像Qt中的布局那样,使它们组织得更有条理。
参考其他博客上的观点,可以将QCustomPlot当作一个二维图表,我们姑且将这些当作坐标轴图层和各种其他图层。坐标轴图形是横轴和纵轴的图层,可设置各种属性,之后会详细讲解。
我们在使用其他图层之前,必须使用函数addGraph()先添加图层,添加的图层从序列号0开始计层数,使用函数graph(index)获取指定图层的指针,获取的图层类似于一张图画;
使用图层指针可以设置画笔setPen()决定线条的颜色,设置画刷setBrush()决定其点连成的线到X轴的颜色,实现两条线之间区域用画刷填充,我们需要设置主从图层,从主图层的点画向从图层的点,此时从图层的画刷设置为透明(缺省为透明,若未修改可不设置),然后设置主图层的画刷颜色为我们需要填充的颜色,并使用函数setChannelFillGraph()从使用主图层的画刷画向从图层,从而填充两者点之间的区域。
在图层上画点,使用addData()函数,图层会将每相邻点之间自动用线调连接起来,当点的数据超出显示范围之后,最好使用removeDataBefore()删除范围外的数据,不然内存将一直增加,QCustomPlot不会自己删除。
2.QCustomPlot帮助文件
在QCustomPlot源码包中,带有qt帮助文件,将其添加进qt帮助文件,添加过程如下图,工具栏选择“工具”,“选项”,“帮助”选择添加文档:
图3添加qcustomeplot帮助文档
之后就可以在帮助文档中查看关于Qcustomplot的帮助文档。
图4 QcustomPlot帮助文档查询
3.环境配置过程
首先下载官方文档,得到文件夹中的文件夹里面的头文件qcustomplot.h和源文件qcustomplot.cpp,将这两个文件加入到新创建的工程中。在 .pro文件中添加printsupport,并保存。
图5 .pro文件中添加printsupport
向主窗口添加一个widget容器控件,输入提升类名称输入“QCustomPlot”,点击添加。右键提升为:
图6 输入提升类QCustomPlot
之后右侧的类会变成QcustomPlot:
图7
直接运行程序出现:
图8 customplot基础曲线框图
我们可以对QCustomPlot做这样的理解:
QCustomPlot就是一个绘图板的类,它继承于Widget,界面中的Widget类提升为QCustomPlot才能够绘图。
QCustomPlot中的每一个曲线是一个Graph对象,凡是跟显示数据有关的我们就对Graph进行操作或调用Graph对象提供的方法。在不做更多设置时,默认显示左侧和下方的坐标轴,刻度为0-5,颜色为黑色。
void firstCustomPlot::InitAPlot()
{
QCustomPlot *p = ui->plot;
p->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom); //可拖拽+可滚轮缩放
p->legend->setVisible(true); //显示图例
p->xAxis->setLabel(QStringLiteral("X轴文字")); //X轴文字显示
p->yAxis->setLabel(QStringLiteral("Y轴文字")); //Y轴文字显示
p->xAxis->setRange(0, 100); //当前X轴显示的范围
p->yAxis->setRange(0, 10); //当前Y轴显示的范围
p->addGraph(); //向绘图区域QCustomPlot添加一条曲线
p->addGraph();
p->graph(0)->setPen(QPen(Qt::red)); //绘制曲线0的画刷颜色为红色
p->graph(1)->setPen(QPen(Qt::blue)); //绘制曲线1的画刷颜色为蓝色
//绘制的曲线轨迹
for (int i = 0; i<100; i++)
{
p->graph(0)->addData(i, i % 10);
p->graph(1)->addData(i, (double)i / 10.0);
}
}
做一个简单的示例:这些都是对放在对曲线进行初始化的函数中,然后在主函数中对其进行调用。运行后得到如下结果。
4.对图例的设置
通过setVisible(true)就可以将图例默认显示在曲线控件的右上角,可以通过如下代码改变图例的位置,有九个位置可选。可以改变如下加粗的部分的代码:
p->axisRect()->insetLayout()
->setInsetAlignment(0,Qt::AlignRight|Qt::AlignBottom); //图例置于右下
/*
Qt::AlignLeft|Qt::AlignTop); //图例置于左上
Qt::AlignCenter|Qt::AlignTop);//图例置于中上
Qt::AlignRight|Qt::AlignTop);//图例置于右上
Qt::AlignLeft|Qt::AlignCenter);//图例置于左中
Qt::AlignCenter); //图例置于正中
Qt::AlignRight|Qt::AlignCenter);//图例置于右中
Qt::AlignLeft|Qt::AlignBottom);//图例置于左下
Qt::AlignCenter|Qt::AlignBottom);//图例置于中下 */
图10 图例的九个摆放位置
九种代码运行结果分别如上所示。这里会发现,图例中的字体的背景颜色都已经发生了改变,可以通过QFont改变图例中的字体,设置画刷改变图例的背景颜色。
QFont legendFont = font(); // start out with MainWindow's font..
legendFont.setPointSize(12); // 图例中的文字设置为12号
p->legend->setFont(legendFont);
p->legend->setBrush(QBrush(QColor(0,255,255,230)));
//图例的背景设置为蓝色
5.对坐标轴和网格颜色的设置
对于曲线的X、Y坐标轴,坐标轴上长短刻度的颜色、数字的颜色,以及从长短刻度中延伸出来的长虚线形成的网格的颜色,零线的颜色都是可以改变的。
p->xAxis->setBasePen(QPen(Qt::black, 1));
//坐标轴的横竖线
p->yAxis->setBasePen(QPen(Qt::black, 1));
//坐标轴的横竖线
p->xAxis->setTickPen(QPen(Qt::green, 1));
//坐标轴有数字的上方的小刻度线的颜色
p->yAxis->setTickPen(QPen(Qt::green, 1));
//坐标轴有数字的上方的小刻度线的颜色
p->xAxis->setSubTickPen(QPen(Qt::red, 1));
//坐标轴上小刻度和末端箭头的颜色
p->yAxis->setSubTickPen(QPen(Qt::red, 1));
//坐标轴上小刻度和末端箭头的颜色
p->xAxis->setTickLabelColor(Qt::blue);
//坐标轴上的数字
p->yAxis->setTickLabelColor(Qt::yellow);
//坐标轴上的数字
p->xAxis->grid()->setPen(QPen(QColor(140, 0, 0), 1, Qt::DotLine));
//X轴数字上延的虚线的画线格式(大刻度)
p->yAxis->grid()->setPen(QPen(QColor(140, 0, 0), 1, Qt::DotLine));
//Y轴数字右延的虚线的画线格式(大刻度)
p->xAxis->grid()->setSubGridPen(QPen(QColor(80, 80, 80), 1, Qt::DotLine));
//X轴无数字处上延的画线格式(小刻度)
p->yAxis->grid()->setSubGridPen(QPen(QColor(80, 80, 80), 1, Qt::DotLine));
//Y轴无数字处右延的画线格式(小刻度)
p->xAxis->grid()->setSubGridVisible(true);
//图表内是否设置网格虚线
p->yAxis->grid()->setSubGridVisible(true);
//图表内是否设置网格虚线
p->xAxis->grid()->setZeroLinePen(Qt::NoPen);
//设置零线画笔,即X轴刻度0处的一条竖线
p->yAxis->grid()->setZeroLinePen(Qt::NoPen);
//设置零线画笔,即Y轴刻度0处的一条横线
如上设置后运行结果如下:
图11 设置网格和坐标轴的颜色和样式结果
注意这里的坐标X轴、Y轴是有上下左右四条的,默认显示如上的X、Y轴,也可以用如下代码的true和false来设置四条坐标轴是否显示。
p->xAxis->setVisible(false); //设置需要显示的坐标轴x
p->yAxis->setVisible(false); //设置需要显示的坐标轴y
p->xAxis2->setVisible(true); //设置需要显示的坐标轴x2
p->yAxis2->setVisible(true); //设置需要显示的坐标轴y2
当我们设置只显示X2和Y2时,运行结果如下:
图12 显示右上的坐标轴
坐标轴末端的箭头由如下代码设置,同样是分四个坐标轴设置:
//为坐标轴添加箭头
p->xAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);
p->yAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);
p->xAxis2->setUpperEnding(QCPLineEnding::esSpikeArrow);
p->yAxis2->setUpperEnding(QCPLineEnding::esSpikeArrow);
注意第三节最开始对短刻度的颜色设置和箭头颜色设置是同一条,即短刻度与箭头是同色的:
p->xAxis->setSubTickPen(QPen(Qt::red, 1));
//坐标轴上小刻度和末端箭头的颜色
p->yAxis->setSubTickPen(QPen(Qt::red, 1));
//坐标轴上小刻度和末端箭头的颜色
运行后得到如下红色的箭头:
图13 将小刻度和末端箭头设置为红色
在第一节的环境配置中,我们有对坐标轴的名称和显示范围进行设置,具体代码如下:
p->xAxis->setRange(0, 100); //x轴的范围
p->yAxis->setRange(0, 10); //y轴的范围
p->xAxis2->setRange(0, 100); //x2轴的范围
p->yAxis2->setRange(0, 10); //y2轴的范围
p->xAxis->setLabel(“xAxis1”); //x1轴名称
p->yAxis->setLabel(“yAxis1”); //y1轴名称
p->xAxis2->setLabel(“xAxis2”); //x2轴名称
p->yAxis2->setLabel(“yAxis2”); //y2轴名称
p->xAxis->setTickLabels(true); //x1轴坐标刻度
p->yAxis->setTickLabels(true); //y1轴坐标刻度
p->xAxis2->setTickLabels(true); //x2轴坐标刻度
p->yAxis2->setTickLabels(true); //y2轴坐标刻度
官方示例文件夹examples中有对图例更进一步使用的例子“interactions”,可以对其中的功能使用进行参考。
关于Interaction-example完成了一个随机曲线显示的功能:
图14 运行Interaction-example
在运行得到的曲线图例上点击右键,弹出选项框,可以将图例的位置做出改变,移动到左上、中上、右上、右下和左下五个位置。
图15 Interaction-example右键图例
双击图例中的某条曲线,曲线的颜色会变为白色,在界面上“消失”,再次双击后以一个随机颜色出现。
图16 Interaction-example双击图例曲线结果
在界面中点击右键,弹出选项框,可以添加随机曲线或者移除所选的曲线或者移除所有曲线。
图17 右键界面前景位置
6.对曲线背景颜色和前景颜色的设置
这里使用QLinearGradient 的渐变色对曲线的背景颜色进行设置。
//设置画布背景色
QLinearGradient plotGradient;
plotGradient.setStart(0, 0);
plotGradient.setFinalStop(0, 350);
plotGradient.setColorAt(0, QColor(80, 80, 80));
plotGradient.setColorAt(1, QColor(50, 50, 50));
p->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));
p->axisRect()->setBackground(axisRectGradient);
如上设置之后也更能看出上节设置之后的效果:
图18 改变背景颜色和前景颜色
7.对数据保存的设置
在环境配置章节中我们展示了由一百个点画成的两条曲线,但是当我们需要画出较多点组成的曲线或者是动态实时更新的曲线时,官方例子中一般使用vector保存数据。比如下面这个小例子,使用QVector保存曲线的横纵坐标。
void trycustomplot::InitPlot()
{
QCustomPlot *p = ui->plot;
QVector<double> x1(100) , y1(100);
for (int i=0; i<x1.size(); ++i)
{
x1[i] = i/(double)(x1.size()-1)*10;
y1[i] = qCos(x1[i]*0.8+qSin(x1[i]*0.16+1.0))*qSin(x1[i]*0.54)+1.4;
}
QCPGraph *graph1 = p->addGraph();
graph1->setData(x1,y1);
p->replot();
}
运行之后得到如下图像:
图19
当数据量特别大的时候,我们就需要考虑将旧数据不断推出去,新数据再不断地加进来,比如在基于DDS的组件化数据监视演示验证系统软件中的曲线控件使用的如下结构保存数据。
void trycustomplot::addData(double x, double y)
{
size++;
if(size==DATA_MAX)
{
xVector.pop_front();
yVector.pop_front();
size–;
}
xVector.push_back(x);
yVector.push_back(y);
}
曲线控件中不会保存传输的所有点,addData()函数将要绘制的点的x,y坐标都各自保存到vector中,设置DATA_MAX=1000,表示要保存的最大数据,当size达到最大时,pop_front()删除第一个数据,size减1,push_back()将新数据添加到末尾。
注意在第一段代码中用到
p->replot();
表示重绘,这里其实也可以不加,但是官方例子有,一般执行setData函数后会自动重绘。我认为它应该用于动态显示或者是改变坐标轴范围之后的动态显示。相应的还有曲线的清除
p->graph(0)->data()->clear();
8.官方示例
从官网中下载的QCustomPlot中提供了4个例子以供我们学习,尤其新入手的范例plot-example,其中包含了多种效果,只需要我们修改如下图第57行的代码数字,就可以实现不同的效果展示:
图20
都是一些很简单的实例,分析便于对各种函数运用的理解。
图21
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/181089.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...