QCustomplot(五)QCPAxisRect进行子绘图

子绘图是比较复杂的,你几乎需要掌握QCustomPlot所有类及其含义。那么需要掌握的类有:

  • QCPAxis 描述轴行为,轴需要依赖QCPAxisRect
  • QCPAxisRect 描述矩形区域,区域依赖于QCPCustomPlot
  • QCPLayoutGrid 网格形排列矩形区域,类似于QGridLayout
  • QCustomPlot 默认行为及对象
  • QLegend 图例

QCustomplot(五)QCPAxisRect进行子绘图_第1张图片

一、QCPAxis 轴对象

1.1 构造
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
1.2 可以设置哪些内容?

构造时用到的两个参数对象是可以返回的:

AxisType axisType () const
QCPAxisRect * axisRect () const

关于网格有以下内容可供设置:
QCustomplot(五)QCPAxisRect进行子绘图_第2张图片
关于留白,有以下内容可供设置:
QCustomplot(五)QCPAxisRect进行子绘图_第3张图片

二、QCPAxisRec 矩形区域

QCPAxisRect是多个轴围成的一个矩形区域,也就是坐标轴,其构造方法如下:

QCPAxisRect (QCustomPlot *parentPlot, bool setupDefaultAxes=true);

第一个参数是父对象QCustomplot,第二个参数是否设置默认轴(四个轴,但是只显示左下)。构造函数告诉我们,QCPAxisRec必须依赖与一个父对象QCustomPlot。

2.1 SetFullAxesBox 设置完全矩形区域

这个函数为一个矩形区域设置四个默认坐标轴,上下和左右的轴属性完全一样;Tick Label左右默认不显示。

2.2 addAxis和addAxes 添加一个轴
QCPAxis * QCPAxisRect::addAxis (QCPAxis::AxisType type, QCPAxis * axis =nullptr);
QList<QCPAxis *> QCPAxisRect::addAxes(QCPAxis::AxisTypes types);

addAxis函数将往矩形区域特定位置添加一个轴(上下左右),第二个参数是一个QCPAxis对象指针,

  • 轴由内部创建。axis 为空指针,表示由内部创建并维护这个轴的生命周期,请不要直接delete返回的轴指针,而是使用removeAxis删除;
  • 轴是外部实例。axis为指向实例的指针,表示这个轴是用户自行创建的,注意轴类型应该与自行创建的时候一致,否则轴将会添加失败;此外,不应该多次添加同一个轴实例。

无论是内部还是外部,轴生命周期都由QCustomPlot控制,同一个位置可以添加多个轴。

2.3 axis 、axes 方法选取轴实例
  • 特定位置轴个数: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等属性

2.3 removeAxis 移除特定轴

添加好的轴可以通过bool QCPAxisRect:removeAxis(QCPAxis *axis)

三、QCPLayoutGrid 将坐标轴按网格排列

什么是网格布局?网格布局就是将一个子元素按照网格的形状排列。元素对象有:
QCustomplot(五)QCPAxisRect进行子绘图_第4张图片

3.1 构造一个QCPLayoutGrid
QCPLayoutGrid::QCPLayoutGrid()

成员函数rowCount和columnCount可以返回当前布局行和列个数。

3.2 addElement 增加一个元素
bool QCPLayoutGrid::addElement(QCPLayoutElement *element);
bool QCPLayoutGrid::addElement(int row,int column,QCPLayoutElement * element);

向布局中增加一个元素,如果对应行列不存在将会扩展它。

3.3 element hasElement 获取一个元素
QCPLayoutElement * QCPLayoutGrid::element(int row,int column) const;
bool QCPLayoutGrid::hasElement(int row,int column);
3.2 simplify、ExpandTo 合并和扩充
void QCPLayoutGrid::expandTo(int newRowCount,int new ColumnCount);
void simplify();

四、QCPLayer 图层

4.1 QCPLayer和QCPLayerable

Layer是可能包含对象的、控制渲染顺序的对象。对于QCustomPlot对象内部具有一个渲染顺序列表,在绘制时将会连续画出QCPLayerable对象。

QCPLayer包含有序的QCPLayerable对象,QCPLayerable是所有可见对象的基类,如:axes、grids、graph和item等。

4.2 默认图层

背景层、网格层、主层、坐标轴层、图例层和矩形选择区域层。

默认情况下,QCustomPlot有六个图层,分别是:“background” “grid” “main” “axes” “legend”和“overlay”(注意顺序)。最先绘制的是“overlay”层,它只包含QCustomPlot选中的矩形(QCustomPlot::selectionRect),往后分别是“axes”和“legend”,表示默认轴和图示,在中间,有一个“main”层,它默认不含任何东西且为默认图层(QCustomPlot::setCurrentLayer)。这也就意味着所有可绘制的对象将会默认在此层,接着是QCPGrid对象(与QCPAxis紧密相连)。轴矩形区域应该绘制在所有图层后边,以便显示数据内容,因此QCPAxisRect实例被放在"background"层,当然你可以设置每个对象所在的图层(QCPLayerable::setLayer)。

4.3 控制图层渲染顺序

在绘制时控制图层非常简单:使用QCustomPlot::addLayer方法创建一个指定层的图层,如在“main”上层,然后用QCustomPlot::setCurrentLayer设置设置为你刚刚创建的图层,接下来的事情,只需要和往常一样创建图层上的对象即可,因为你设置了当前图层,所以对象都将会放置在该图层。如果你觉得比较麻烦,可以创建出了图层之后直接使用QCPLayer::setLayer将所有对象放在指定图层。你甚至可以移动整个图层的内容,方法是QCustomPlot::moveLayer。在同一图层内点的对象是覆盖形式的,删除一个图层不会删除对应的的对象QCustomPlot::removeLayer。

五、QCPLegend 图例

该对象管理了一个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)));

结果如下:
QCustomplot(五)QCPAxisRect进行子绘图_第5张图片


[1] https://www.qcustomplot.com/index.php/support/forum/314

你可能感兴趣的:(#,QT,QCustomPlot,subplot,QT)