[QCustomPlot] 绘图截图:高级轴演示 Plot Screenshots: Advanced Axes Demo

本篇为官方例子的解读:绘图截图:高级轴演示 Plot Screenshots: Advanced Axes Demo
推荐其他人总结的笔记:qcustomplot使用教程–基本绘图

在这里插入图片描述

1.删除原有的默认布局

    customPlot->plotLayout()->clear(); // 清除默认的rect轴,以便我们可以从头开始        
    customPlot->replot(); // 重绘

在这里插入图片描述

在这里插入图片描述

  • 原先默认有一个(0,5)范围的坐标轴布局, 执行代码后直接清空变全白了.

2.插入坐标轴

    customPlot->plotLayout()->clear(); // 清除默认的rect轴,以便我们可以从头开始

    QCPAxisRect *wideAxisRect = new QCPAxisRect(customPlot);    // 一个坐标轴
    QCPLayoutGrid *subLayout = new QCPLayoutGrid;               // 一个布局网络

    customPlot->plotLayout()->addElement(0, 0, wideAxisRect);   // 坐标轴放第一行
    customPlot->plotLayout()->addElement(1, 0, subLayout);      // 布局放第二行

    QCPAxisRect *subRectLeft = new QCPAxisRect(customPlot, false);  // 一个坐标轴 false表示不设置默认轴
    QCPAxisRect *subRectRight = new QCPAxisRect(customPlot, false); // 一个坐标轴 false表示不设置默认轴
    
    subRectLeft->addAxes(QCPAxis::atBottom | QCPAxis::atLeft);      // 添加下面和左边的坐标轴
    subRectRight->addAxes(QCPAxis::atBottom | QCPAxis::atRight);    // 添加下面和右边的坐标轴

    subLayout->addElement(0, 0, subRectLeft);                       // 坐标轴放在左边
    subLayout->addElement(0, 1, subRectRight);                      // 坐标轴放在右边

    customPlot->replot(); // 重绘

在这里插入图片描述

  • 可以看到第一行上面的坐标是默认带网格的.下面第二行两个坐标轴就算只有坐标轴的;

3.重叠坐标轴

    // # 3.重叠坐标轴
    wideAxisRect->setupFullAxesBox(true);                           // 设置右和上坐标轴的可见性,并将左和下坐标轴的属性给予右和上坐标轴, 注意,这一步执行完后右和上坐标轴是没有数值的,只有刻度
    wideAxisRect->axis(QCPAxis::atRight, 0)->setTickLabels(true);   // 第一个函数是获取右边索引第一个的坐标轴, 然后使其显示数字
    wideAxisRect->addAxis(QCPAxis::atLeft)->setTickLabelColor(QColor("#6050F8")); // 在左边(再)添加一个坐标轴,并且设置数字的颜色

在这里插入图片描述

  • 注意其中用到的添加重叠坐标轴的函数addAxis(),和索引坐标轴的函数axis();
  • 右和上坐标轴的范围被赋予和左下坐标轴一样;

4.坐标轴尺寸与刻度

    // # 4.坐标轴尺寸与刻度
    subRectRight->setMaximumSize(150, 150);     // 设置最大尺寸
    subRectRight->setMinimumSize(150, 150);     // 设置最小尺寸, 结合相当于是固定尺寸

    subRectLeft->axis(QCPAxis::atLeft)->ticker()->setTickCount(2);      // 左坐标轴范围不变, 主刻度只有2个
    subRectRight->axis(QCPAxis::atRight)->ticker()->setTickCount(2);    // 右坐标轴范围不变, 主刻度只有2个
    subRectRight->axis(QCPAxis::atBottom)->ticker()->setTickCount(2);   // 下坐标轴范围不变, 主刻度只有2个
    subRectLeft->axis(QCPAxis::atBottom)->grid()->setVisible(true);     // 下坐标轴的网格线显示可见

在这里插入图片描述

  • 注意,设置坐标轴尺寸后,会自动填满;而且下面2个坐标轴的左右已经和上面1个坐标轴不对齐了;
  • 注意,要设置坐标轴刻度相关的,先获取坐标轴axis()再获取刻度ticker(),
  • 类似的,要设置网格线相关的,先获取坐标轴axis()再获取刻度grid(),

5.归类分组

    // 同步顶部和底部轴矩形的左右边距:
    QCPMarginGroup *marginGroup = new QCPMarginGroup(customPlot);           // 创建一个用于同步关联的对象
    subRectLeft->setMarginGroup(QCP::msLeft, marginGroup);                  // 丢入三个坐标轴中
    subRectRight->setMarginGroup(QCP::msRight, marginGroup);                // 丢入三个坐标轴中
    wideAxisRect->setMarginGroup(QCP::msLeft | QCP::msRight, marginGroup);  // 丢入三个坐标轴中

    //移动“轴”层上新创建的轴和“网格”层上的网格:
    foreach (QCPAxisRect *rect, customPlot->axisRects())      // 获取所有坐标轴
    {
        foreach (QCPAxis *axis, rect->axes())                 // 获取所有x和y坐标轴
        {
            axis->setLayer("axes");                           // 将坐标轴归类分组
            axis->grid()->setLayer("grid");                   // 将所有网格线归类分组
        }
    }
    
    // 生成数据, 留着备用
    QVector<QCPGraphData> dataCos(21), dataGauss(50), dataRandom(100);
    QVector<double> x3, y3;
    qsrand(3);
    for (int i=0; i<dataCos.size(); ++i)
    {
      dataCos[i].key = i/static_cast<double>(dataCos.size()-1)*10-5.0;
      dataCos[i].value = qCos(dataCos[i].key);
    }
    for (int i=0; i<dataGauss.size(); ++i)
    {
      dataGauss[i].key = i/static_cast<double>(dataGauss.size())*10-5.0;
      dataGauss[i].value = qExp(-dataGauss[i].key*dataGauss[i].key*0.2)*1000;
    }
    for (int i=0; i<dataRandom.size(); ++i)
    {
      dataRandom[i].key = i/static_cast<double>(dataRandom.size())*10;
      dataRandom[i].value = qrand()/static_cast<double>(RAND_MAX)-0.5+dataRandom[qMax(0, i-1)].value;
    }
    x3 << 1 << 2 << 3 << 4;
    y3 << 2 << 2.5 << 4 << 1.5;

在这里插入图片描述

  • 对比上一个,下面2个坐标轴已经和上面1个坐标轴的左右对齐了;
  • 这个对齐和分组的方法有点难以理解,暂时死记好了.

6.画2个折线图

    // # 6.画2个折线图
    QCPGraph *mainGraphCos = customPlot->addGraph(wideAxisRect->axis(QCPAxis::atBottom), wideAxisRect->axis(QCPAxis::atLeft)); // 添加一条折线图,使用下面第一个和左边第一个坐标轴
    mainGraphCos->data()->set(dataCos);                     // 设置数据
    mainGraphCos->valueAxis()->setRange(-1, 1);             // 设置y轴范围
    mainGraphCos->rescaleKeyAxis();                         // 设置x轴自适应
    mainGraphCos->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, QPen(Qt::black), QBrush(Qt::white), 6)); // 设置散点样式
    mainGraphCos->setPen(QPen(QColor(120, 120, 120), 2));   // 设置线颜色

    QCPGraph *mainGraphGauss = customPlot->addGraph(wideAxisRect->axis(QCPAxis::atBottom), wideAxisRect->axis(QCPAxis::atLeft, 1)); // 再添加一条折线图,使用下面第一个和左边第二个坐标轴
    mainGraphGauss->data()->set(dataGauss);                 // 设置数据
    mainGraphGauss->valueAxis()->setRange(0, 1000);         // 设置y轴范围
    mainGraphGauss->rescaleKeyAxis();                       // 设置x轴自适应
    mainGraphGauss->setPen(QPen(QColor("#8070B8"), 2));     // 设置线颜色

    mainGraphGauss->setBrush(QColor(110, 170, 110, 30));    // 设置和x轴的闭合填充颜色
    mainGraphCos->setChannelFillGraph(mainGraphGauss);      // 修改第一条折线的默认闭合空间
    mainGraphCos->setBrush(QColor(255, 161, 0, 50));        // 设置和的第二条折线的闭合填充颜色, 注意, 闭合空间有重叠的部分, 后配置的会覆盖前配置的

在这里插入图片描述

  • 注意,添加折线使用函数,addGraph(),然后会返回句柄,使用该句柄配置折线,可以使用graph(0)获取已经添加的折线图层;
  • 注意,折线默认的闭合空间是和KeyAxis坐标轴,可以通过函数setChannelFillGraph()修改为特定曲线;
  • 注意,图像有重叠的优先级之分, 也可能是先后之分, 具体…自己实测吧.

7.画1个类似柱状图的图

    // # 7.画1个类似柱状图的图
    QCPGraph *subGraphRandom = customPlot->addGraph(subRectLeft->axis(QCPAxis::atBottom), subRectLeft->axis(QCPAxis::atLeft));
    subGraphRandom->data()->set(dataRandom);                // 设置数据
    subGraphRandom->setLineStyle(QCPGraph::lsImpulse);      // 设置直线类型 lsImpulse 每个数据点由一条平行于值轴的线表示,该线从数据点延伸到零值线
    subGraphRandom->setPen(QPen(QColor("#FFA100"), 1.5));   // 设置线颜色
    subGraphRandom->rescaleAxes();                          // 设置xy轴自适应

在这里插入图片描述

  • 注意使用函数rescaleAxes()一次性自适应两个轴,
  • 注意,纵坐标依旧只有两个主刻度;
  • 这个线的类型有点像柱状图;

8.画一个柱状图

    // # 8.画一个柱状图
    QCPBars *subBars = new QCPBars(subRectRight->axis(QCPAxis::atBottom), subRectRight->axis(QCPAxis::atRight)); // 添加一个柱状图
    subBars->setWidth(3/static_cast<double>(x3.size()));    // 设置柱状图的宽度, 计算平均一点
    subBars->setData(x3, y3);                               // 设置数据
    subBars->setPen(QPen(Qt::black));                       // 设置线颜色
    subBars->setAntialiased(false);                         // 设置此对象是否绘制为反锯齿
    subBars->setAntialiasedFill(false);                     // 设置此绘图对象的填充是否绘制为反锯齿
    subBars->setBrush(QColor("#705BE8"));                   // 设置柱状填充颜色
    subBars->keyAxis()->setSubTicks(false);                 // 刻度尺上的次刻度,隐藏
    subBars->rescaleAxes();                                 // 设置xy轴自适应

    // 为subBars键轴设置一个仅给出整数刻度的自动收报机:
    QSharedPointer<QCPAxisTickerFixed> intTicker(new QCPAxisTickerFixed); // 创建一个刻度
    intTicker->setTickStep(1.0);                            // 设置刻度的间距
    intTicker->setScaleStrategy(QCPAxisTickerFixed::ssMultiples); // 允许指定刻度步长的整数倍
    subBars->keyAxis()->setTicker(intTicker);               // 将该刻度对象赋值给凸显

在这里插入图片描述

  • 注意, 柱状图使用的是函数QCPBars(),不同于折线图,
  • 注意,柱状图一般都要关闭绘画抗锯齿;
  • 注意,柱状图要设置柱子的宽度,不然会密密麻麻连成一片;
  • 注意,柱状图一般要重新设置横坐标,

9.总结

  • 至此分析完成;
  • 上面的代码全部拼在一起就好了.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值