Qt之开源绘图控件QCustomPlot

文章目录

  • 前言
  • 一、QCustomPlot 是什么?
  • 二、基本概念
    • 1.QCustomPlot
    • 2.QCPLayer
    • 3.QCPAbstractPlottable
  • 三、简单使用
  • 四、简单封装
  • 总结


前言

QCustomPlot是一个开源的基于Qt的第三方绘图库,能够绘制漂亮的2D图形。
QCustomPlot的官方网址:https://www.qcustomplot.com/
从官网下载QCustomPlot的源文件,包括qcustomplot.h和qcustomplot.cpp。


一、QCustomPlot 是什么?

QCustomPlot 是一个Qt三方图表库,在 QChart 还未免费开放时,应该是一个很受欢迎的三方库。即使现在 QChart 已经可以免费使用了,有些功能使用 QCustomPlot 实现,体验也非常棒!下图为 QCustomPlot官网 的一些示例,非常丰富。
Qt之开源绘图控件QCustomPlot_第1张图片

二、基本概念

1.QCustomPlot

图表类:用于图表的显示和交互

2.QCPLayer

图层:管理图层元素(QCPLayerable),所有可显示的对象都是继承自图层元素

3.QCPAbstractPlottable

绘图元素,包含以下几种:

  • QCPGraph(折线图)
  • QCPCurve(曲线图)
  • QCPBars(柱状图)
  • QCPStatiBox(盒子图)
  • QCPColorMap(色谱图)
  • QCPFinancial(金融图)
    QCPAxisRect
    坐标轴矩形:一个坐标轴矩形默认包含上下左右四个坐标轴,但是可以添加多个坐标轴
    Qt之开源绘图控件QCustomPlot_第2张图片
    示例程序的源码下载地址:
    https://download.csdn.net/download/qq_34623621/86735907
    取其 qcustomplot.cpp 和 qcustomplot.h;将其加入工程。

三、简单使用

    QVector<double> x(101), y(101);
    for (int i = 0; i < 101; ++i) {
        x[i] = i / 50.0 - 1; // -1 到 1
        y[i] = x[i] * x[i];
    }

    QCustomPlot* customPlot = ui->customPlot;
    customPlot->setOpenGl(true);
    customPlot->addGraph();
    customPlot->graph(0)->setData(x, y);
    customPlot->graph(0)->setName("TEST");
    customPlot->xAxis->setLabel("x");
    customPlot->yAxis->setLabel("y");
    customPlot->xAxis->setRange(-1, 1);
    customPlot->yAxis->setRange(0, 1);
    customPlot->legend->setVisible(true);

    customPlot->replot();

Qt之开源绘图控件QCustomPlot_第3张图片
坐标轴

// 自动扩展
customPlot->rescaleAxes();
customPlot->replot(QCustomPlot::rpQueuedReplot);

// 可滚动可缩放
customPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom);

/*! QCPAxis有相应的函数可以设置坐标轴的刻度、间距、范围等 */
//设置刻度间距
setTickStep(double step);
//将坐标轴刻度设置为vec
setTickVector(const QVector<double> &vec);
//设置是否自动分配刻度间距
setAutoTickStep(bool on);
//设置是否自动分配刻度
setAutoTicks(bool on);
//设置是否自动分配刻度数量
setAutoTickCount(int approximateCount);

曲线

// 设置曲线画笔
customPlot->graph(0)->setLineStyle((QCPGraph::lsStepLeft));

// 设置曲线上点的风格(样式)
customPlot->graph(0)->setScatterStyle(QCPScatterStyle(QCPScatterStyle::ssCircle, 5));

// 设置曲线风格
QPen graphPen;
graphPen.setColor(qcolor);
graphPen.setWidthF(2);
customPlot->graph(0)->setPen(graphPen);

//设置曲线形状
QCPGraph::setBrush(const QBrush &brush);
//设置与某之间曲线填充
QCPGraph::setChannelFillGraph(otherGraph);
//移除填充
QCPGraph::setBrush(Qt::NoBrush);

图例

// 图例默认是关闭的,需要我们开启
customPlot->legend->setVisible(true);

// 设置图例行优先排列
customPlot->legend->setFillOrder(QCPLayoutGrid::foColumnsFirst);
// 设置六个图例自动换行
customPlot->legend->setWrap(6);

// 设置图例位置
customPlot->axisRect()->insetLayout()->setInsetAlignment(0, Qt::AlignHCenter|Qt::AlignTop);
// 设置边框隐藏
customPlot->legend->setBorderPen(Qt::NoPen);

四、简单封装

创建曲线

QCPGraph* newLine(QCustomPlot *customPlot,QString lineName,QColor color,bool isPointLine = false){
    QCPGraph *mGraph = customPlot->addGraph();
    mGraph->setName(lineName);
    if(isPointLine){
        mGraph->setPen(QPen());
    }
    QPen graphPen;
    graphPen.setColor(color);
    graphPen.setWidthF(rand()/(double)RAND_MAX*2+1);
    mGraph->setPen(graphPen);
    return mGraph;
}

获取曲线

void getLine(QCustomPlot *customPlot,QString lieName,QCPGraph* & graph, QColor color,bool isPointLine = false){
    graph = nullptr;
    for(int i = 0; i < customPlot->graphCount(); i++){
        QCPGraph *currLine = customPlot->graph(i);
        if(lieName == currLine->name()){
            graph =  currLine;
        }
    }
    if(nullptr == graph){
        graph = newLine(customPlot,lieName,color,isPointLine);
    }
}

添加数据点
注意:这里我们仅保留当前y轴大小的点数据。避免持续追加数据时避免内存无限增长~

void addPoint(QCustomPlot *customPlot,QString lineName, double data, int maxCount ,bool pointDisplay){

    QCPGraph *mGraph = nullptr;
    getLine(customPlot,lineName,mGraph,QColor(rand()%245+10, rand()%245+10, rand()%245+10),pointDisplay);

    /*! Y Axis auto adjustment*/
//    if(data > customPlot->yAxis->range().upper){
//        double yMin = customPlot->yAxis->range().lower;
//        int tickCount = customPlot->yAxis->ticker().data()->tickCount();
//        int tickSize =  customPlot->yAxis->range().upper/tickCount;
//        double yMax = ((data/tickSize)+1)*tickSize;
//        customPlot->yAxis->setRange(yMin,yMax);

//        qDebug() << " tickCount= " << tickCount << " tickSize= " << tickSize <<  " yMax= " << yMax;
//    }

    int pointCount = mGraph->dataCount();
    QCPGraphDataContainer * mDataContainer = mGraph->data().data();
    QVector<QCPGraphData> mOldPoints;
    mDataContainer->getData(mOldPoints);
    QVector<double> newKeys;
    QVector<double> newValues;
    if(pointCount > maxCount){
        for(int i =1; i < pointCount; i++){
            double x = mOldPoints.at(i).key;
            double y = mOldPoints.at(i).value;
            newKeys.append(x-1);
            newValues.append(y);
        }
        double x = mOldPoints.at(pointCount-1).key;
        newKeys.append(x);
        newValues.append(data);
        mGraph->setData(newKeys,newValues);
        customPlot->rescaleAxes();
        customPlot->replot(QCustomPlot::rpQueuedReplot);
    }else{
        double x = mOldPoints.at(pointCount - 1).key;
        mGraph->addData(x + 1,data);
        customPlot->rescaleAxes();
        customPlot->replot(QCustomPlot::rpQueuedReplot);
    }
}

动态图表

    /*! Legend */
    ui->customPlot->legend->setVisible(true);

    QTimer *timer = new QTimer;
    ui->customPlot->xAxis->setRange(1,2);
    ui->customPlot->rescaleAxes();
    static double i = 0;
    connect(timer,&QTimer::timeout,[=]{
        if(ui->customPlot->xAxis->range().upper < maxCount){
            i++;
            ui->customPlot->xAxis->setRange(1,i);
        }
        addPoint(ui->customPlot,"V3",qrand()%20,maxCount,false);
        addPoint(ui->customPlot,"V1",qrand()%10,maxCount,false);
    });
    timer->start(200);


总结

以上就是今天要讲的内容,本文仅仅简单介绍了QCustomPlot的使用,而QCustomPlot提供了大量能使我们快速便捷地处理数据的函数和方法。

你可能感兴趣的:(数据结构快速入门,qt,开源,开发语言)