QCustomPlot是一个开源的基于Qt的第三方绘图库,能够绘制漂亮的2D图形。
QCustomPlot的官方网址:https://www.qcustomplot.com/
从官网下载QCustomPlot的源文件,包括qcustomplot.h和qcustomplot.cpp。
QCustomPlot 是一个Qt三方图表库,在 QChart 还未免费开放时,应该是一个很受欢迎的三方库。即使现在 QChart 已经可以免费使用了,有些功能使用 QCustomPlot 实现,体验也非常棒!下图为 QCustomPlot官网 的一些示例,非常丰富。
图表类:用于图表的显示和交互
图层:管理图层元素(QCPLayerable),所有可显示的对象都是继承自图层元素
绘图元素,包含以下几种:
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();
// 自动扩展
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提供了大量能使我们快速便捷地处理数据的函数和方法。