您的当前位置:首页正文

QCustomPlot系列(2)-绘制两条曲线+自动全显+鼠标拖放+rescaleAxes()函数简介

2024-11-05 来源:个人技术集锦

如下图所示:官网给出了几个最简单的绘图示例,位于Basic plotting:

接下来我们将以官网给出的绘制两条曲线为例,看看QCustomPlot的用法。先看下效果图

 

首先在ui中拖出一个QWidget,命名为customPlot,然后右击提升为QCustomPlot,然后添加代码:

以下代码是官网的,我把注释修改成了中文:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    QCustomPlot *customPlot = ui->customPlot;

    //每条曲线都会独占一个graph()
    customPlot->addGraph();
    customPlot->graph(0)->setPen(QPen(Qt::blue)); // 曲线的颜色
    customPlot->graph(0)->setBrush(QBrush(QColor(0, 0, 255, 20))); // 曲线与X轴包围区的颜色
    customPlot->addGraph();//添加graph等价于添加新曲线
    customPlot->graph(1)->setPen(QPen(Qt::red)); // 曲线的颜色
    // 生成模拟数据点 (x-y0 第一条曲线, x-y1为第2条曲线):
    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); // 第一条曲线:y0衰减cos
      y1[i] = qExp(-i/150.0);              // 第二条曲线:y1衰减指数
    }
    // 边框右侧和上侧均显示刻度线,但不显示刻度值:
    // (参见 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);
    // 使上下两个X轴的范围总是相等,使左右两个Y轴的范围总是相等
    connect(customPlot->xAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->xAxis2, SLOT(setRange(QCPRange)));
    connect(customPlot->yAxis, SIGNAL(rangeChanged(QCPRange)), customPlot->yAxis2, SLOT(setRange(QCPRange)));
    // 把已存在的数据填充进graph的数据区
    customPlot->graph(0)->setData(x, y0);
    customPlot->graph(1)->setData(x, y1);
    //自动调整XY轴的范围,以便显示出graph(0)中所有的点(下面会单独讲到这个函数)
    customPlot->graph(0)->rescaleAxes();
    //自动调整XY轴的范围,以便显示出graph(1)中所有的点
    customPlot->graph(1)->rescaleAxes(true);
    // 支持鼠标拖拽轴的范围、滚动缩放轴的范围,左键点选图层(每条曲线独占一个图层)
    customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectPlottables);
    // 立即刷新图像
    ui->customPlot->replot();
}

 

简单说一下QCustomPlot绘图的几个概念和机制:

1、每一条曲线都必须独占一个graph,新建graph可通过addGraph()来实现。
2、每一个QCustomPlot都有上下左右4个坐标轴,分别为customPlot->xAxis2、xAxis、yAxis、yAxis2。
每个轴可设置是否显示、是否显示刻度、几个刻度、刻度的值是否显示等。
尤其注意:上下两个X轴可以设置不同的可视范围,不同的图层可以绑定其中一个X轴,customPlot->addGraph(customPlot->xAxis2, customPlot->yAxis2),addGraph默认是绑定下X轴、左Y轴。

 

在一个plot中可以显示多个图层(曲线),由于每条曲线的XY轴的范围可能都不一样,如何在plot中把它们都全显出来?

需要用到“自动缩放轴的范围”函数:rescaleAxes( bool  onlyEnlarge = false)。
该函数的作用是,使当前plot的XY的显示范围恰好(不能大也不能小)容纳本图层(曲线),如果plot中有多条曲线,我们依次执行:
customPlot->graph(0)->rescaleAxes();  
customPlot->graph(1)->rescaleAxes();
。。。//略
customPlot->graph(N)->rescaleAxes();


那么最终的显示效果就是,plot的XY轴的范围恰好容纳graph(N),而我们希望plot能恰好容纳graph(0)到graph(N),那么就得这样写:
customPlot->graph(0)->rescaleAxes();  
customPlot->graph(1)->rescaleAxes(true);
。。。//略(全都是true)
customPlot->graph(N)->rescaleAxes(true);

我们发现这个函数带个参数onlyEnlarge,这个参数的意义是,如果plot的X或Y轴本来能容纳下本graph的X或Y数据点,那么plot的X或Y轴的可视范围就无需调整,只有plot容纳不下本graph时,才扩展plot两个轴的显示范围。也即如参数名onlyEnlarge所示,plot的可视范围只扩大,不缩小。这样才能实现显示所有曲线。

帮助文档也说了,给第一个graph设置rescaleAxes(),后续所有graph都设置rescaleAxes(true)即可实现显示所有曲线。

下面我们将写一个函数,执行该函数后,可以使plot显示出所有曲线:

void QCustomPlot::showAllGraph()
{
    /*方法1*/
//    if(this->graphCount() > 0)
//        this->graph(0)->rescaleAxes(false);//调整plot的XY轴使之恰好容纳第一条曲线
//    for(int idx = 1; idx < this->graphCount(); idx++)
//    {
//        this->graph(idx)->rescaleAxes(true);//扩大plot的XY轴使之能容纳其他曲线
//    }
//    this->replot();//立即刷新图像

    /*方法2*/
    this->xAxis->rescale(true);//调整X轴的范围,使之能显示出所有的曲线的X值
    this->yAxis->rescale(true);//调整Y轴的范围,使之能显示出所有的曲线的Y值
}

然后我们就能用ui->customedplot->showAllGraph()来一键显示所有曲线了。

 

 

Top