QCustomPlot开发笔记:QCustomPlot简介下载以及基础绘图

Posted 长沙红胖子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了QCustomPlot开发笔记:QCustomPlot简介下载以及基础绘图相关的知识,希望对你有一定的参考价值。

若该文为原创文章,转载请注明原文出处
本文章博客地址:https://hpzwl.blog.csdn.net/article/details/124527752

红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中…(点击传送门)

Qt开发专栏:三方库开发技术

上一篇:没有了
下一篇:《QCustomPlot开发笔记(二):QCustomPlot用户交互、元素项以及特殊用法》


前言

  QCustomPlot开发笔记系列整理集合,这是目前使用最为广泛的Qt图表类(Qt的QWidget代码方向只有QtCharts,Qwt,QCustomPlot),使用多年,系统性的整理,过目并整理了原有文档,本系列旨在系统解说并逐步更新其各种Demo示例。


多年前文章

  (本篇不再整理了)
  《Qt开发笔记之QCustomPlot:QCustomPlot介绍、编译与使用


QCustomPlot介绍

简介

  QCustomPlot是一个小型的qt画图标类,效果可以,易用,只需要在项目中加入头文件qcustomplot.hqcustomplot.cpp文件,然后使一个widget提升为QCustomPlot类,即可使用。
  QCustomPlot 可以导出为各种格式,如矢量化 PDF 文件和光栅化图像,如 PNG、JPG 和 BMP。QCustomPlot 是在应用程序内显示实时数据以及为其他媒体生成高质量绘图的解决方案。

支持的图形

  下图显示了使用 QCustomPlot 仅用几行可以实现的功能。要查看代码,请单击相应的图像。所有代码也可在完整包中找到。
  

优点与缺点

从性能角度

  QCustomPlot是一个比较完善的框架,其框架和缓存化的处理使其处理性能大幅度提升(设置笔宽为1,可撑起几百万点),而QtCharts只是一个半成品,不论是否有bug,QtCharts在两千个点以内是可以使用的,超过两千个点就存在刷新卡顿的问题(很大可能)。

从定制化角度

  QCustomPlot修改源码因为其是一步一步继承过来的,修改起来是比较麻烦的,还需要反复调试以防止修改了代码出现了其他问题,入添加一个少则半天一天,多则几天,所以如果需要定制修改QCustomoPlot源码的需求,是需要进一步仔细评估是否值得这么做。

下载地址

  最新版本:2.1.0
  
  官网:https://www.qcustomplot.com/index.php/introduction
  CSDN粉丝零积分下载:https://download.csdn.net/download/qq21497936/85250427
  QQ群:1047134658(点击“文件”搜索“qcustomplot”,群内与博文同步更新)


QCustomPlot的部署

  直接下载后,将其中的qcstomplot.hqcustomplot.cpp当作项目文件添加即可:
  
  更好的方式是模块化部署,如下图;
  


QCustomPlot基础绘图

  (注意:以下示例使用customPlot作为指向QCustomPlot实例的指针。在QtCreator中升级了一个小部件,可能会通过ui->customPlot(或者给小部件起的任何名字)访问相应的小部件。)

添加图形

  可以通过customPlot->addGraph()在绘图中创建新的图形。然后为图形指定一些数据点,例如通过customPlot->graph(0)->setData(…),例如,以两个QVector< double >的形式表示x和y(键和值)。QCustomPlot使用术语键和值而不是x和y的原因是,在指定哪个轴具有什么角色时允许更大的灵活性。
  因此,如果将左轴定义为“关键轴”,将底部定义为“值轴”,则可以绘制一个竖立在绘图左侧的图形。默认情况下,QCustomPlot小部件有四个轴:customPlot->xAxis、yAxis、xAxis2和QCPAxis类型的yAxis2,对应于底部、左侧、顶部和右侧轴。它们的范围定义了绘图的当前可见部分:customPlot->xAxis->setRange(-1,1)。

// generate some data:
QVector<double> x(101), y(101); // initialize with entries 0..100
for (int i=0; i<101; ++i)

  x[i] = i/50.0 - 1; // x goes from -1 to 1
  y[i] = x[i]*x[i]; // let's plot a quadratic function

// create graph and assign data to it:
customPlot->addGraph();
customPlot->graph(0)->setData(x, y);
// give the axes some labels:
customPlot->xAxis->setLabel("x");
customPlot->yAxis->setLabel("y");
// set axes ranges, so we see all data:
customPlot->xAxis->setRange(-1, 1);
customPlot->yAxis->setRange(0, 1);
customPlot->replot();

  
  轴当前使用的轴标记器会自动选择标记步骤和标签。这是QCPAxisTicker类型的实例,可以通过xAxis->ticker() 访问。可以通过xAxis->ticker()->setTickCount(6) 调整ticker尝试创建的大致刻度数。默认的轴标记器非常适合简单的数字显示,但是有专门的类别,例如时间跨度、日历日期、类别、pi(或其他符号单位)和对数轴。参阅QCPAxisTicker文档。
  轴的刻度标签(数字)永远不会到达小部件边界之外,即使它们变宽了。这是由于默认情况下启用了自动保证计算。如果记号标签和轴标签需要更多空间,它会使轴矩形收缩。如果不希望自动确定边距,请通过调用customPlot->axisRect()->setAutoMargins(QCP::msNone) 禁用该行为。然后可以通过customPlot->axisRect()->setMargins(…) 手动调整边距。

视图定制

图形

  图形的外观由许多因素决定,所有这些因素都可以修改。以下是最重要的:

  • 线型:调用graph->setLineStyle(…)。有关所有可能的线条样式,请参阅QCPGraph::LineStyle文档或简介页面上的线条样式演示屏幕截图。
  • 线条笔:QPainter 框架提供的所有笔都可用,例如实线、虚线、点线、不同的宽度、颜色、透明度等。通过 设置配置的笔graph->setPen(…)
  • 散点符号:调用 graph->setScatterStyle(…) 以更改散点符号的外观。对于所有可能的散布样式,请参阅QCPScatterStyle文档。如果不希望在数据点处显示任何散点符号,请将图形的散点样式设置为 QCPScatterStyle::ssNone
  • 在图形下或两个图形之间填充:QPainter 框架提供的所有画笔都可以用于图形填充:实心、各种图案、纹理、渐变、颜色、透明度等,通过设置配置画笔graph->setBrush(…)

  轴的外观可以通过更改其绘制的笔及其标签使用的字体来修改。查看QCPAxis的文档应该是不言自明的。下面是最重要属性的快速总结:setBasePensetTickPensetTickLengthsetSubTickLengthsetSubTickPensetTickLabelFontsetLabelFontsetTickLabelPaddingsetLabelPadding。可以使用setRangeReversed反转轴(例如,使值从左到右减少而不是增加)。如果要在轴端进行装饰(如箭头),请使用setLowerEnding或SetPerEnding。

网格线

  通过访问axis的相应QCPGrid实例来修改网格。例如,通过访问**customPlot->yAxis->grid()来更改与左轴相连的水平网格线的外观。网格线的外观基本上是用画笔绘制的,可以通过yAxis->grid()->setPen()进行设置。勾号0处的网格线可以使用其他笔绘制,也可以使用setZeroLinePen进行配置。如果不想用特殊的钢笔画零线,只需将其设置为Qt::NoPen,勾号0处的网格线将用普通的网格笔画出来。
默认情况下,子栅格线设置为不可见。可以使用
grid()->setSubGridVisible(true)**使其可见。

官方示例

  两个图的简单图
  下面是一个创建具有指数包络的衰减余弦函数图像的示例:
  

// add two new graphs and set their look:
customPlot->addGraph();
// line color blue for first graph
customPlot->graph(0)->setPen(QPen(Qt::blue)); 
// first graph will be filled with translucent blue
customPlot->graph(0)->setBrush(QBrush(QColor(0, 0, 255, 20)));  
// line color blue for second graph
customPlot->addGraph();
// line color red for second graph
customPlot->graph(1)->setPen(QPen(Qt::red)); 
// 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;
  // exponentially decaying cosine
  y0[i] = qExp(-i/150.0)*qCos(i/10.0); 
  // exponential envelope
  y1[i] = qExp(-i/150.0);              

// configure right and top axis to show ticks but no labels:
// (see QCPAxisRect::setupFullAxesBox for a quicker method to do this)
customPlot->xAxis2->setVisible(true);
customPlot->xAxis2->setTickLabels(false);
customPlot->yAxis2->setVisible(true);
customPlot->yAxis2->setTickLabels(false);
// make left and bottom axes always transfer their ranges to right and top axes:
connect(customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->xAxis2, SLOT(setRange(QCPRange)));
connect(customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->yAxis2, SLOT(setRange(QCPRange)));
// pass data points to graphs:
customPlot->graph(0)->setData(x, y0);
customPlot->graph(1)->setData(x, y1);
// let the ranges scale themselves so graph 0 fits perfectly in the visible area:
customPlot->graph(0)->rescaleAxes();
// same thing for graph 1, but only enlarge ranges (in case graph 1 is smaller than graph 0):
customPlot->graph(1)->rescaleAxes(true);
// Note: we could have also just called customPlot->rescaleAxes(); instead
// Allow user to drag axis ranges with mouse, zoom with mouse wheel and select graphs by clicking:
customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);

  以上,是将填充应用于图形就像设置一个不是Qt::NoBrush的笔刷一样简单。填充将从图形(此处为图形0)到与键(此处为x)轴平行的零值线。如果我们想在这个图和另一个图之间填充通道,我们会另外调用graph->setChannelFillGraph(otherGraph)。要删除通道填充,只需像其他图形一样传递0,填充将像以前一样一直到达零值线。要完全删除填充,请调用graph->setBrush(Qt::NoBrush)
使用多轴打印和更高级的样式
  一个更复杂的示例,用于创建演示如下图,其中包含四个轴上的五个图形、纹理填充、垂直错误条、图例、小数点分隔符等。

// period as decimal separator and comma as thousand separator
customPlot->setLocale(QLocale(QLocale::English, QLocale::UnitedKingdom)); 
customPlot->legend->setVisible(true);
// start out with MainWindow's font..
QFont legendFont = font();  
// and make a bit smaller for legend
legendFont.setPointSize(9); 
customPlot->legend->setFont(legendFont);
// by default, the legend is in the inset layout of the main axis rect. So this is how we access it to change legend placement:
customPlot->legend->setBrush(QBrush(QColor(255,255,255,230)));
customPlot->axisRect()->insetLayout()->setInsetAlignment(0, Qt::AlignBottom|Qt::AlignRight);
// setup for graph 0: key axis left, value axis bottom
// will contain left maxwell-like function
customPlot->addGraph(customPlot->yAxis, customPlot->xAxis);
customPlot->graph(0)->setPen(QPen(QColor(255, 100, 0)));
// fill with texture of specified image
customPlot->graph(0)->setBrush(QBrush(QPixmap("./balboa.jpg"))); 
customPlot->graph(0)->setLineStyle(QCPGraph::lsLine);
customPlot->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssDisc, 5));
customPlot->graph(0)->setName("Left maxwell function");

// setup for graph 1: key axis bottom, value axis left (those are the default axes)
// will contain bottom maxwell-like function with error bars
customPlot->addGraph();
customPlot->graph(1)->setPen(QPen(Qt::red));
// same fill as we used for graph 0
customPlot->graph(1)->setBrush(QBrush(QPixmap("./balboa.jpg"))); 
customPlot->graph(1)->setLineStyle(QCPGraph::lsStepCenter);
customPlot->graph(1)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, Qt::red, Qt::white, 7));
customPlot->graph(1)->setName("Bottom maxwell function");
QCPErrorBars *errorBars = new QCPErrorBars(customPlot->xAxis, customPlot->yAxis);
errorBars->removeFromLegend();
errorBars->setDataPlottable(customPlot->graph(1));

// setup for graph 2: key axis top, value axis right
// will contain high frequency sine with low frequency beating:
customPlot->addGraph(customPlot->xAxis2, customPlot->yAxis2);
customPlot->graph(2)->setPen(QPen(Qt::blue));
customPlot->graph(2)->setName("High frequency sine");

// setup for graph 3: same axes as graph 2
// will contain low frequency beating envelope of graph 2
customPlot->addGraph(customPlot->xAxis2, customPlot->yAxis2);
QPen blueDotPen;
blueDotPen.setColor(QColor(30, 40, 255, 150));
blueDotPen.setStyle(Qt::DotLine);
blueDotPen.setWidthF(4);
customPlot->graph(3)->setPen(blueDotPen);
customPlot->graph(3)->setName("Sine envelope");
 
// setup for graph 4: key axis right, value axis top
// will contain parabolically distributed data points with some random perturbance
customPlot->addGraph(customPlot->yAxis2, customPlot->xAxis2);
customPlot->graph(4)->setPen(QColor(50, 50, 50, 255));
customPlot->graph(4)->setLineStyle(QCPGraph::lsNone);
customPlot->graph(4)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 4));
customPlot->graph(4)->setName("Some random data around\\na quadratic function");
 
// generate data, just playing with numbers, not much to learn here:
QVector<double> x0(25), y0(25);
QVector<double> x1(15), y1(15), y1err(15);
QVector<double> x2(250), y2(250);
QVector<double> x3(250), y3(250);
QVector<double> x4(250), y4(250);
for (int i=0; i<25; ++i) // data for graph 0

  x0[i] = 3*i/25.0;
  y0[i] = qExp(-x0[i]*x0[i]*0.8)*(x0[i]*x0[i]+x0[i]);

for (int i=0; i<15; ++i) // data for graph 1

  x1[i] = 3*i/15.0;;
  y1[i] = qExp(-x1[i]*x1[i])*(x1[i]*x1[i])*2.6;
  y1err[i] = y1[i]*0.25;

for (int i=0; i<250; ++i) // data for graphs 2, 3 and 4

  x2[i] = i/250.0*3*M_PI;
  x3[i] = x2[i];
  x4[i] = i/250.0*100-50;
  y2[i] = qSin(x2[i]*12)*qCos(x2[i])*10;
  y3[i] = qCos(x3[i])*10;
  y4[i] = 0.01*x4[i]*x4[i] + 1.5*(rand()/(double)RAND_MAX-0.5) + 1.5*M_PI;

 
// pass data points to graphs:
customPlot->graph(0)->setData(x0, y0);
customPlot->graph(1)->setData(x1, y1);
errorBars->setData(y1err);
customPlot->graph(2)->setData(x2, y2);
customPlot->graph(3)->setData(x3, y3);
customPlot->graph(4)->setData(x4, y4);
// activate top and right axes, which are invisible by default:
customPlot->xAxis2->setVisible(true);
customPlot->yAxis2->setVisible(true);
// set ranges appropriate to show data:
customPlot->xAxis->setRange(0, 2.7);
customPlot->yAxis->setRange(0, 2.6);
customPlot->xAxis2->setRange(0, 3.0*M_PI);
customPlot->yAxis2->setRange(-70, 35);
// set pi ticks on top axis:
customPlot->xAxis2->setTicker(QSharedPointer<QCPAxisTickerPi>(new QCPAxisTickerPi));
// add title layout element:
customPlot->plotLayout()->insertRow(0);
customPlot->plotLayout()->addElement(0, 0, new QCPTextElement(customPlot, "Way too many graphs in one plot", QFont("sans", 12, QFont::Bold)))QCustomPlot版本迭代日志

Qt使用QCustomPlot开发

Qt Widget使用QCustomPlot库实现二维螺旋曲线(螺旋曲线一)

Qt Widget使用QCustomPlot库实现二维螺旋曲线(螺旋曲线一)

Qt Widget使用QCustomPlot库实现二维螺旋曲线(螺旋曲线一)

Qt Widget使用QCustomPlot库实现二维螺旋曲线(螺旋曲线一)