子绘图是比较复杂的,你几乎需要掌握QCustomPlot所有类及其含义。那么需要掌握的类有:
QCPAxis::QCPAxis (QCPAxisRect * parent, AxisType type);
可以看出QCPAxis依赖与QCPAxisRect对象的,关于第二个参数enum QCPAxis::AxisType
,就是表明其在矩形中的位置:
枚举类型 | 编号 | 含义 |
---|---|---|
atLeft | 0x01 | Axis is vertical and on the left side of the axis rect |
atRight | 0x02 | Axis is vertical and on the right side of the axis rect |
atTop | 0x04 | Axis is horizontal and on the top side of the axis rect |
atBottom | 0x08 | Axis is horizontal and on the bottom side of the axis rect |
构造时用到的两个参数对象是可以返回的:
AxisType axisType () const
QCPAxisRect * axisRect () const
关于网格有以下内容可供设置:
关于留白,有以下内容可供设置:
QCPAxisRect是多个轴围成的一个矩形区域,也就是坐标轴,其构造方法如下:
QCPAxisRect (QCustomPlot *parentPlot, bool setupDefaultAxes=true);
第一个参数是父对象QCustomplot,第二个参数是否设置默认轴(四个轴,但是只显示左下)。构造函数告诉我们,QCPAxisRec必须依赖与一个父对象QCustomPlot。
这个函数为一个矩形区域设置四个默认坐标轴,上下和左右的轴属性完全一样;Tick Label左右默认不显示。
QCPAxis * QCPAxisRect::addAxis (QCPAxis::AxisType type, QCPAxis * axis =nullptr);
QList<QCPAxis *> QCPAxisRect::addAxes(QCPAxis::AxisTypes types);
addAxis函数将往矩形区域特定位置添加一个轴(上下左右),第二个参数是一个QCPAxis对象指针,
无论是内部还是外部,轴生命周期都由QCustomPlot控制,同一个位置可以添加多个轴。
int QCPAxisRect::axisCount(QCPAxis type) const
返回,QCPAxis *QCPAxisRect::axis(QCPAxis::AxisType type,int index=0) const
QList QCPAxisRect::axes(QCPAxis::AxisType types)const
QList QCPAxisRect::axes ( ) const
那么选取轴实例有什么用呢?答:可以控制轴标签、tick等属性
添加好的轴可以通过bool QCPAxisRect:removeAxis(QCPAxis *axis)
什么是网格布局?网格布局就是将一个子元素按照网格的形状排列。元素对象有:
QCPLayoutGrid::QCPLayoutGrid()
成员函数rowCount和columnCount可以返回当前布局行和列个数。
bool QCPLayoutGrid::addElement(QCPLayoutElement *element);
bool QCPLayoutGrid::addElement(int row,int column,QCPLayoutElement * element);
向布局中增加一个元素,如果对应行列不存在将会扩展它。
QCPLayoutElement * QCPLayoutGrid::element(int row,int column) const;
bool QCPLayoutGrid::hasElement(int row,int column);
void QCPLayoutGrid::expandTo(int newRowCount,int new ColumnCount);
void simplify();
Layer是可能包含对象的、控制渲染顺序的对象。对于QCustomPlot对象内部具有一个渲染顺序列表,在绘制时将会连续画出QCPLayerable对象。
QCPLayer包含有序的QCPLayerable对象,QCPLayerable是所有可见对象的基类,如:axes、grids、graph和item等。
背景层、网格层、主层、坐标轴层、图例层和矩形选择区域层。
默认情况下,QCustomPlot有六个图层,分别是:“background” “grid” “main” “axes” “legend”和“overlay”(注意顺序)。最先绘制的是“overlay”层,它只包含QCustomPlot选中的矩形(QCustomPlot::selectionRect),往后分别是“axes”和“legend”,表示默认轴和图示,在中间,有一个“main”层,它默认不含任何东西且为默认图层(QCustomPlot::setCurrentLayer)。这也就意味着所有可绘制的对象将会默认在此层,接着是QCPGrid对象(与QCPAxis紧密相连)。轴矩形区域应该绘制在所有图层后边,以便显示数据内容,因此QCPAxisRect实例被放在"background"层,当然你可以设置每个对象所在的图层(QCPLayerable::setLayer)。
在绘制时控制图层非常简单:使用QCustomPlot::addLayer方法创建一个指定层的图层,如在“main”上层,然后用QCustomPlot::setCurrentLayer设置设置为你刚刚创建的图层,接下来的事情,只需要和往常一样创建图层上的对象即可,因为你设置了当前图层,所以对象都将会放置在该图层。如果你觉得比较麻烦,可以创建出了图层之后直接使用QCPLayer::setLayer将所有对象放在指定图层。你甚至可以移动整个图层的内容,方法是QCustomPlot::moveLayer。在同一图层内点的对象是覆盖形式的,删除一个图层不会删除对应的的对象QCustomPlot::removeLayer。
该对象管理了一个QCustomPlot的一个图例。它是一个小的Box区域,包含名称和图标。通过QCPAbstarctPlottable::adddToLegend来填充QCPLegend内容,对于主图示(QCustomPlot::legend)仅需设置QCustomPlot::setAutoAddPlottableToLegend为true(默认行为)就可以自动创建一些legend项,legend是一个与特定可绘制对象相关的对象,可以被QCPAbstractPlottable::removeFromLegend去除。
此外,QCPLegend提供了一些接口增加和直接管理这些legend:item、itemWithPlottable、itemCount、addItem、removeItem等。因为QCPLegend是从QCPLayoutGrid继承而来的,因此通过对象QCPLayoutElement可以将legend添加到任意位置,legend是QCPLayoutElement的元素,默认情况下每一个QCustomPlot只有一个legend(QCustomPlot::legend),表示主轴的内嵌布局中(QCPAxisRect::insetLayout),你可以通过QCPLayoutInset实现在矩形区域移动,使用QCPLayout/QCPLayoutElement接口实现矩形外移动。
终于看完了QCPAxis、QCPAxisRect和QCPLayoutGrid,最后补充一些QCustomPlot本身的一些方法就可以进行子绘图了:
QCPGraph *addGraph(QCPAxis *keyAxis=nullptr,QCPAxis *valueAxis=nullptr);//默认是左下两个轴,你也可以指定特定的轴
QCPGraph *graph()const;
QCPGraph *graph(int index)const;
bool removeGraph(QCPGraph * graph);
bool removeGraph(int index);
bool clearGraph();
int graphCount()const ;
QCPLayoutGrid * QCustomPlot::plotLayout()const;//返回顶层QCustomPlot的布局,通常内容只是一个矩形区域
//Generate data
QVector<double> x,ys,yc,y_cs;
for(double xi=-2*M_PI;xi<2*M_PI;xi+=0.1)
{
x.push_back(xi);
ys.push_back(sin(xi));
yc.push_back(cos(xi));
y_cs.push_back(sin(xi)+cos(xi));
}
//Create Rectangle Area and add to QCustomplot
QCPAxisRect * R00=new QCPAxisRect(this->ui->qcust_curve);
QCPAxisRect * R10=new QCPAxisRect(this->ui->qcust_curve);
QCPAxisRect * R20=new QCPAxisRect(this->ui->qcust_curve);
this->ui->qcust_curve->plotLayout()->clear();
this->ui->qcust_curve->plotLayout()->addElement(0,0,R00);
this->ui->qcust_curve->plotLayout()->addElement(1,0,R10);
this->ui->qcust_curve->plotLayout()->addElement(2,0,R20);
//Draw graphs with data
this->ui->qcust_curve->addGraph(R00->axis(QCPAxis::atBottom),R00->axis(QCPAxis::atLeft));
this->ui->qcust_curve->addGraph(R10->axis(QCPAxis::atBottom),R10->axis(QCPAxis::atLeft));
this->ui->qcust_curve->addGraph(R20->axis(QCPAxis::atBottom),R20->axis(QCPAxis::atLeft));
this->ui->qcust_curve->graph(0)->setData(x,ys);
this->ui->qcust_curve->graph(0)->rescaleAxes();
this->ui->qcust_curve->graph(0)->setName("y=sin(x)");
this->ui->qcust_curve->graph(1)->setData(x,yc);
this->ui->qcust_curve->graph(1)->rescaleAxes();
this->ui->qcust_curve->graph(1)->setName("y=cos(x)");
this->ui->qcust_curve->graph(2)->setData(x,y_cs);
this->ui->qcust_curve->graph(2)->rescaleAxes();
this->ui->qcust_curve->graph(2)->setName("y=cos(x)+sin(x)");
//Add Legends
QCPLegend *arLegend00=new QCPLegend;
R00->insetLayout()->addElement(arLegend00,Qt::AlignTop|Qt::AlignRight);
arLegend00->setLayer("legend");
arLegend00->addItem(new QCPPlottableLegendItem(arLegend00, this->ui->qcust_curve->graph(0)));
QCPLegend *arLegend10=new QCPLegend;
R10->insetLayout()->addElement(arLegend10,Qt::AlignTop|Qt::AlignRight);
arLegend10->setLayer("legend");
arLegend10->addItem(new QCPPlottableLegendItem(arLegend10, this->ui->qcust_curve->graph(1)));
QCPLegend *arLegend20=new QCPLegend;
R20->insetLayout()->addElement(arLegend20,Qt::AlignTop|Qt::AlignRight);
arLegend20->setLayer("legend");
arLegend20->addItem(new QCPPlottableLegendItem(arLegend20, this->ui->qcust_curve->graph(2)));
[1] https://www.qcustomplot.com/index.php/support/forum/314