QCustomPlot single and multiple coordinate system display

Table of Contents

1 renderings

2 Function description

3 key codes

1 Realize the addition, deletion and dynamic update of multiple coordinate systems

2 Coordinate system X-axis synchronization

3 Display cursor in multiple coordinate systems

4 Add curve function

5 Create a single X-axis and multiple Y-axis coordinate system


1 Rendering

2 Function Description

0 Three modes (1) Single X and single Y axis (2) Single X and multiple Y axes (3) Multiple X and multiple Y axes

1. Switching between single coordinate system and multiple coordinate systems is possible.

2 Click the checkbox of QTableWidget to control the number of coordinate systems and display the corresponding curve

3 Display cursor in multiple coordinate systems

4 Change the color of the curve

5 Coordinate system X-axis synchronization

6. Zoom in and out, move left and right, and move up and down the curve

3 key code

Some functions in the header file:

public:
    int m_WaveIndex;
    QCPMarginGroup *marginGroup;
    QString currentFileName;
    int model;
    QVector<QCPAxisRect *>axisList;
    SetYValueDialog mSetYValueDialog;
    RecFile *pRecGlobal;
    bool bCursorMoveShow;
    QVector<QCPItemText *> vectorQCPItemText;
    QCPAxisRect * rect;
    void SetModelState(Model _model);
    void UpdataAll();
    void ModelSingleCoord();
    void ModelXMulY_Coord();
    void ModelMulCoord();
    void ModelChange(int _model = 0);
    void RemoveQCPAxisRectAll();
    void SetVisbleQCPAxisRect();
    void CreateQCPAxisRect();
    void connectAllxAsix(bool on);
    void CreateQCPAxisRect(int axis_num);
    void UpdataViewTable();
    void ClearViewTable();
    void ReloadCustomPlot();
    void loadFileTXTFile(QString fileName);
    void ClearQCPItemText();
    void dragEnterEvent(QDragEnterEvent *event) override; //Drag event

    void dropEvent(QDropEvent *event) override; //Drag and release event
};
1 Realize the addition, deletion and dynamic update of multiple coordinate systems
void MainWindow::RemoveQCPAxisRectAll()
{
    ui->customplot->clearGraphs();
    for(int i = 0;i < axisList.count();i + + )
    {
        ui->customplot->plotLayout()->remove(axisList.at(i));
        QCPAxisRect * rect = axisList.at(i);
        rect = nullptr;
    }
    axisList.clear();
    //My personal understanding here is to rearrange the layout after deleting elements.
    //The number of elements will not change without execution
    ui->customplot->plotLayout()->simplify();
    qDebug()<<ui->customplot->plotLayout()->elementCount();


}

This function deletes all the coordinate axes in QVectoraxisList, but does not delete the default one of QCustomPlot, that is, the default index of ui->customplot->axisRect() is 0, which is not deleted.

void MainWindow::CreateQCPAxisRect(int axis_num)
{

    ui->customplot->plotLayout()->setMargins(QMargins(0, 10, 0, 0));
    ui->customplot->plotLayout()->elementAt(0)->setMarginGroup(QCP::msLeft, marginGroup);
    for(int i = 0;i < axis_num;i + + ){

        QCPAxisRect *rect = new QCPAxisRect(ui->customplot);

        rect->setMarginGroup(QCP::msLeft, marginGroup);
        rect->setAutoMargins(QCP::MarginSide::msLeft | QCP::MarginSide::msRight);
        
        rect->axis(QCPAxis::atBottom)->setRange(0,2000);
        rect->setRangeDrag(Qt::Horizontal | Qt::Vertical); //Horizontal drag

        rect->setRangeZoom(Qt::Horizontal | Qt::Vertical); //Horizontal scaling
        if(i == axis_num - 1)
        {
            rect->setMargins(QMargins(0, 0, 0, 20));
        }

        if(!ui->customplot->plotLayout()->hasElement(i + 1,0))
            ui->customplot->plotLayout()->addElement(i + 1,0,rect);

        axisList.append(rect);

    }
    connectAllxAsix(true);
    ui->customplot->plotLayout()->simplify();

}

This function creates multiple coordinate systems and adds them to the border group marginGroup to keep the Y axis consistent. Since there is a default coordinate system, here is i + 1

ui->customplot->plotLayout()->addElement(i + 1,0,rect);
2 Coordinate system X-axis synchronization
void MainWindow::connectAllxAsix(bool on)
{

    for (int i = 0; i < axisList.count(); + + i) {
        if(on){
            connect(ui->customplot->axisRect()->axis(QCPAxis::atBottom), SIGNAL(rangeChanged(QCPRange)), axisList.at(i)->axis(QCPAxis::atBottom), SLOT(setRange(QCPRange )));
            connect(axisList.at(i)->axis(QCPAxis::atBottom), SIGNAL(rangeChanged(QCPRange)), ui->customplot->axisRect()->axis(QCPAxis::atBottom), SLOT(setRange(QCPRange )));
        }
        else
        {
            disconnect(ui->customplot->axisRect()->axis(QCPAxis::atBottom), SIGNAL(rangeChanged(QCPRange)), axisList.at(i)->axis(QCPAxis::atBottom), SLOT(setRange(QCPRange )));
            disconnect(axisList.at(i)->axis(QCPAxis::atBottom), SIGNAL(rangeChanged(QCPRange)), ui->customplot->axisRect()->axis(QCPAxis::atBottom), SLOT(setRange(QCPRange )));
        }

        for (int j = i + 1; j < axisList.count(); + + j) {
            if(on)
            {

                connect(axisList.at(i)->axis(QCPAxis::atBottom), SIGNAL(rangeChanged(QCPRange)), axisList.at(j)->axis(QCPAxis::atBottom), SLOT(setRange(QCPRange))) ;
                connect(axisList.at(j)->axis(QCPAxis::atBottom), SIGNAL(rangeChanged(QCPRange)), axisList.at(i)->axis(QCPAxis::atBottom), SLOT(setRange(QCPRange))) ;
            }
            else
            {
                disconnect(axisList.at(i)->axis(QCPAxis::atBottom), SIGNAL(rangeChanged(QCPRange)), axisList.at(j)->axis(QCPAxis::atBottom), SLOT(setRange(QCPRange))) ;
                disconnect(axisList.at(j)->axis(QCPAxis::atBottom), SIGNAL(rangeChanged(QCPRange)), axisList.at(i)->axis(QCPAxis::atBottom), SLOT(setRange(QCPRange))) ;
            }

        }
    }
}

This function connects signals and slots to achieve synchronization of the X axis

3 Display cursor in multiple coordinate systems
void MainWindow::mouseMoveEvent( QMouseEvent *event ) {
    //return ;
    if ( !ui->customplot->viewport().contains( event->pos() ) )
        return;
    if ( RubBand->isVisible() ) {
        QPoint EndPoint = event->pos();
        EndPoint.setY(EndPoint.y() + 58);

// EndPoint.setY( ui->customplot->height() );
        RubBand->setGeometry( QRect( StartPoint, EndPoint ).normalized() );
    }

    if(!bCursorMoveShow)
        return ;
    //Get the mouse coordinates, relative to the coordinates of the parent form
    int x_pos = event->pos().x();
    int y_pos = event->pos().y();
    double x_val = 0; //ui->customplot->xAxis->pixelToCoord( x_pos );
    double y_val = 0; //ui->customplot->yAxis->pixelToCoord( y_pos );
    //Mouse coordinates are converted to CustomPlot internal coordinates
    for(int i = 0;i < ui->customplot->axisRectCount(); i + + )
    {
        if(event->pos().x() > ui->customplot->axisRects().at(i)->left() & amp; & amp; event->pos().y() < ui ->customplot->axisRects().at(i)->bottom()\
                 & amp; & amp;event->pos().x() <ui->customplot->axisRects().at(i)->right() & amp; & amp; event->pos().y () > ui->customplot->axisRects().at(i)->top())
        {
            //Don't convert like this
// x_val = ui->customplot->axisRects().at(i)->axis(QCPAxis::atBottom)->pixelToCoord(x_pos);
// y_val = ui->customplot->axisRects().at(i)->axis(QCPAxis::atLeft)->pixelToCoord(y_pos);
            tracer->setClipAxisRect(ui->customplot->axisRects().at(i));
            tracerLabel->setClipAxisRect(ui->customplot->axisRects().at(i));

        }
    }
    x_val = ui->customplot->xAxis->pixelToCoord(x_pos);
    y_val = ui->customplot->yAxis->pixelToCoord(y_pos);
    qDebug()<<"x_val:"<<x_val<<",y_val:"<<y_val;
    QList<QCPGraph*> listQCPGraph = ui->customplot->selectedGraphs();
    if(listQCPGraph.isEmpty())
    {
        tracer->setVisible(false);
        //bSelectGraph = false;
        tracerLabel->setVisible(false);
        ui->customplot->replot();
    }
    else
    {
        QCPGraph* curGraph = listQCPGraph.at(0);
        CDatabind* pUserDat = (CDatabind*)curGraph->userData(0);
        double value;
        double num = 0;
        int index = x_val;
        if(pUserDat)
        {
            int m_nWaveInd = pUserDat->m_nWaveInd;
            num = curGraph->data()->at(index)->key;
            value = curGraph->data()->at(index)->value;
            for(int j = mMoveTime[m_nWaveInd].count() -1; j >= 0;j--)
            {
                sMoveTime var;
                var = mMoveTime[m_nWaveInd].at(j);
                if(var.name == "Y*")
                {
                    if(var.num != 0)
                    {
                        value = value / var.num;
                       
                    }

                }
                else
                {
                    value = value - var.num;
                }
            }

        }
        QString mGraphInfo;

        mGraphInfo = m_pViewTable->currentItem()->text();

        tracer->setVisible(true);
        tracerLabel->setVisible(true);

        tracer->position->setCoords(x_val, y_val);

        tracerLabel->setText( mGraphInfo + "\\
( X:" + QString::number(num) +
                             ",Y:" + QString::number(value) + " )" );
        pCurLabel[0]->setText("CurX:" + QString::number(num));
        pCurLabel[1]->setText("CurY:" + QString::number(value));
        ui->customplot->replot();
    }
}

The mouseMoveEvent function has been rewritten, where

tracer->setClipAxisRect(ui->customplot->axisRects().at(i));
tracerLabel->setClipAxisRect(ui->customplot->axisRects().at(i));

is the key. The if(pUserDat) fragment is to restore the actual values of operations such as curve zooming, zooming, and translation. You can ignore it.

4 Add curve function
void MainWindow::InsertGraph(RecFile *pRec,int nWaveInd){
    QCPGraph *graph;
    Qt::CheckState bSet;
    bSet = m_pViewTable->item(nWaveInd,0)->checkState();

    if(!bSet & amp; & amp; model == sMulCoord )
        graph = ui->customplot->addGraph(ui->customplot->axisRect()->axis(QCPAxis::atBottom),\
                                         ui->customplot->axisRect()->axis(QCPAxis::atLeft));
    else if(model == sMulCoord & amp; & amp; axisList.at(m_WaveIndex) != nullptr){
        graph = ui->customplot->addGraph(axisList.at(m_WaveIndex)->axis(QCPAxis::atBottom),axisList.at(m_WaveIndex )->axis(QCPAxis::atLeft));
        m_WaveIndex + + ;
    }
    else
        graph = ui->customplot->addGraph(ui->customplot->axisRect()->axis(QCPAxis::atBottom),\
                                         ui->customplot->axisRect()->axis(QCPAxis::atLeft));

    graph->setVisible(bSet);
    graph->setData(pRec->Key,pRec->DatWave[nWaveInd]);

    graph->setPen(QPen(QColor::fromHsl((nWaveInd * 30) % 256,255 - (nWaveInd * 30) / 16,128)));
    graph->setName(m_pViewTable->item(nWaveInd,0)->text());
    CDatabind *m_pUserData = new CDatabind();
    m_pUserData->SetUserData(pRec->nFileInd,nWaveInd);
    graph->setUserData(0,m_pUserData);
    graph->setAdaptiveSampling(true);
}

The definitions of many variables are not written out and can be flexibly changed as needed.

5 Create a single X-axis and multiple Y-axis coordinate system
void MainWindow::ModelXMulY_Coord()
{
    ui->customplot->plotLayout()->setMargins(QMargins(0, 10, 0, 0));
    ui->customplot->plotLayout()->elementAt(0)->setMarginGroup(QCP::msLeft, marginGroup);
    for(int i = 0;i < m_pViewTable->rowCount();i + + ){
        QCPAxis *newAxis = new QCPAxis(ui->customplot->axisRect(),QCPAxis::atLeft);
        newAxis->setBasePen(QPen(m_pViewTable->item(i,1)->backgroundColor()));
        newAxis->setTickLabelColor(m_pViewTable->item(i,1)->backgroundColor());
        //Add multiple Y axes
        ui->customplot->axisRect()->addAxis(QCPAxis::atLeft,newAxis);
        axisList_Y.append(newAxis);

    }
    //Depending on whether the CheckBox is visible
    for(int i = 0;i < m_pViewTable->rowCount() ;i + + ){
        if(!m_pViewTable->item(i,0)->checkState())
            ui->customplot->axisRect()->axis(QCPAxis::atLeft,i + 1)->setVisible(false);
    }
    //Whether to display Y-axis coordinates
    if(!bShowYCoord){
        for(int i = 0;i < m_pViewTable->rowCount() ;i + + ){

            ui->customplot->axisRect()->axis(QCPAxis::atLeft,i + 1)->setVisible(false);
        }

    }
    qDebug()<<"ModelXMulY_Coord"<<ui->customplot->axisRect()->axes().count();
    qDebug()<<"ModelXMulY_Coord QCPAxis::atLeft"<<ui->customplot->axisRect()->axes(QCPAxis::atLeft).count();
    ui->customplot->plotLayout()->simplify();

    horizontal.clear();
    horizontal.append(ui->customplot->axisRect()->axis(QCPAxis::atBottom));
    //Set the scaling of the Y-axis coordinate system
    ui->customplot->axisRect()->setRangeZoomAxes(horizontal,axisList_Y);

}