QT custom control line chart and trend chart.

There are two implementation methods provided here, one is self-drawn custom control, and the other is third-party SDK (qcustomplot).
Here I mainly introduce the self-drawn one. Its advantages are simple structure, easy to modify the code logic, and easy customization. Its disadvantage is that its functions are relatively simple. The advantages of third-party qcustomplot are rich functions and outstanding performance. The disadvantage is that the code structure is complex and difficult to quickly customize according to actual needs.

Please add image description
Please add image description
Please add image description
Please add image description
Please add image description
Please add image description

Method 1:
Interface introduction:

//Incoming data, add according to actual situation.
struct ChartPointInfo
{ ChartPointInfo(); ChartPointInfo(double tyAxisval,QColor tcolor,double tline_Wide = 1,quint64 txAxis = 0) { yAxisval= tyAxisval;color = tcolor;line_Wide = tline_Wide;xAxis = txAxis; } double yAxisval; quint64 xAxis; QColor color; double line_Wide = 0; };








void addPointInfo(ChartPointInfo ptinfo); //单个数据增加。
void setData(QList<ChartPointInfo> &datas); //批量数据整体赋值。

void setxAxisUnit(QString val); //设置x轴名称
void setyAxisUnit(QString val); //设置y轴名称
void setShowType(int num){m_showType = num;} //设置显示类型。0:显示规定长度的数据;1:显示所有数据。
void setChartType(int num){m_chartType = num;}//设置表的类型。0:柱状图;1:折线图。
void setChartModel(int num){m_chartModel = num;}//设置x轴单位模式。0:数值;1:时间。
void setxAxisRange(int min,int max){m_xAxisMin = min;m_xAxisMax = max;}//设置x轴范围
void setyAxisRange(int min,int max){m_yAxisMinVal = min;m_yAxisMaxVal = max;}//设置y轴范围

Call interface:

        MChartCurve* curveChart = new MChartCurve();
        curveChart->setFixedSize(500,300);
        curveChart->setxAxisUnit("TIME");
        curveChart->setyAxisUnit("(单位:L)");
        curveChart->setShowType(1);
        curveChart->setChartType(0);
        curveChart->setChartModel(0);

Implementation code:
.h

#ifndef MCHARTCURVE_H
#define MCHARTCURVE_H

#include <QWidget>
#include <QPainter>

struct ChartPointInfo
{
    
    
    ChartPointInfo();
    ChartPointInfo(double toilConspn,QColor tcolor,double tline_Wide = 1,quint64 txAxis = 0)
    {
    
    
        oilConspn = toilConspn;color = tcolor;line_Wide = tline_Wide;xAxis = txAxis;
    }

    double oilConspn = 0.0;
    quint64 xAxis;
    QColor color;
    double line_Wide = 0;
};

class MChartCurve : public QWidget
{
    
    
    Q_OBJECT
public:
    MChartCurve(QWidget* parent = nullptr);
    ~MChartCurve();
    void addPointInfo(ChartPointInfo ptinfo);
    void setData(QList<ChartPointInfo> &datas);

    void setxAxisUnit(QString val);
    void setyAxisUnit(QString val);
    void setShowType(int num){
    
    m_showType = num;}
    void setChartType(int num){
    
    m_chartType = num;}
    void setChartModel(int num){
    
    m_chartModel = num;}
    void setxAxisRange(int min,int max){
    
    m_xAxisMin = min;m_xAxisMax = max;}
    void setyAxisRange(int min,int max){
    
    m_yAxisMinVal = min;m_yAxisMaxVal = max;}
protected:
    void paintEvent(QPaintEvent *event);
    void timerEvent(QTimerEvent *event);
private:
    QList<ChartPointInfo> m_chartPtInfos;
    double m_yAxisSize = 10;
    double m_yAxisMaxVal = 100;
    double m_yAxisMinVal = 0;
    double m_xAxisSize = 5;
    double m_xAxisMax = 10;
    double m_xAxisMin = 0;
    int m_showType = 1;
    int m_chartType = 0;
    int m_chartModel = 0;
    QString m_xAxisUnit;
    QString m_yAxisUnit;
    qint64 m_timeSpec = 0;

};

#endif // MCHARTCURVE_H

.cpp

#include "mchartcurve.h"
#include <QDateTime>
#include <QDebug>
#include <QApplication>

MChartCurve::MChartCurve(QWidget *parent) /*: QWidget(parent)*/
{
    
    
    //    this->setAttribute(Qt::WA_TranslucentBackground);
    startTimer(1000);  //模拟数据
}

MChartCurve::~MChartCurve()
{
    
    

}

//模拟数据
void MChartCurve::timerEvent(QTimerEvent *event)
{
    
    
    addPointInfo(ChartPointInfo(rand()%(int)m_yAxisMaxVal,QColor(rand()%255,rand()%255,rand()%255),0.5));
}

void MChartCurve::addPointInfo(ChartPointInfo ptinfo)
{
    
    
    static uint initTime = QDateTime::currentDateTime().toTime_t();

    //模拟数据
    ptinfo.xAxis = QDateTime::currentDateTime().toTime_t() - initTime;

    m_timeSpec = initTime;
    m_chartPtInfos.append(ptinfo);

    if (m_showType == 0)
    {
    
    
        if (m_chartPtInfos.size() > m_xAxisMax-m_xAxisMin + 1)
        {
    
    
            m_chartPtInfos.removeFirst();
            m_xAxisMin++;
            m_xAxisMax++;
        }
    }
    else
    {
    
    
        if (m_xAxisMax < ptinfo.xAxis)
            m_xAxisMax = m_xAxisMax*2;
    }
    update();
}

void MChartCurve::setData(QList<ChartPointInfo>& datas)
{
    
    
    m_chartPtInfos = datas;
    if (m_showType == 0)
    {
    
    
        if (m_chartPtInfos.size() > m_xAxisMax-m_xAxisMin + 1)
        {
    
    
            m_chartPtInfos.removeFirst();
            m_xAxisMin++;
            m_xAxisMax++;
        }
    }
    else
    {
    
    
        if (m_xAxisMax < datas.last().xAxis)
            m_xAxisMax = m_xAxisMax*2;
    }
    update();
}

void MChartCurve::paintEvent(QPaintEvent *event)
{
    
    
    QPainter p(this);
    p.setRenderHint(QPainter::Antialiasing);
    QPen pen;
    QFont font;

    double xstartPos = 30;                 //x轴全局坐标起始点
    double ystartPos = 10;                 //y轴全局坐标起始点
    double xWidth = width() - 80;
    double yHeight = height() - 40;
    double yAxisSize = m_yAxisSize;        //x轴刻度数
    double yAxisMaxVal = m_yAxisMaxVal;
    double xAxisSize = m_xAxisSize;        //y轴刻度数
    double xAxisMax = m_xAxisMax;
    double xAxisMin = m_xAxisMin;

    //chart
    double xAxisTextLen = xWidth/(xAxisMax - xAxisMin);
    double yAxisTextLen = yHeight/yAxisMaxVal;
    for (int i = 0; i < m_chartPtInfos.size() - 1; i++)
    {
    
    
        ChartPointInfo startinfo = m_chartPtInfos[i];
        ChartPointInfo endinfo = m_chartPtInfos[i+1];
        pen.setWidthF(startinfo.line_Wide);
        pen.setColor(startinfo.color);
        p.setPen(pen);
        p.setBrush(QBrush(startinfo.color));

        if (m_chartType == 1)
            p.drawRect(QRectF(xstartPos + (startinfo.xAxis-xAxisMin)*xAxisTextLen,ystartPos + (yAxisMaxVal-startinfo.oilConspn)*yAxisTextLen,
                              qAbs(endinfo.xAxis - startinfo.xAxis)*xAxisTextLen,10 + yHeight - (ystartPos + (yAxisMaxVal-startinfo.oilConspn)*yAxisTextLen)));
        else
            p.drawLine(QPointF(xstartPos + (startinfo.xAxis-xAxisMin)*xAxisTextLen,ystartPos + (yAxisMaxVal-startinfo.oilConspn)*yAxisTextLen)
                       ,QPointF(xstartPos + (endinfo.xAxis-xAxisMin)*xAxisTextLen,ystartPos + (yAxisMaxVal-endinfo.oilConspn)*yAxisTextLen));

    }

    //base line
    double oilprec = 0.6;
    double baseyPos = yAxisMaxVal * (1 - oilprec) * yAxisTextLen;
    pen.setStyle(Qt::DashLine);
    pen.setColor(QColor("#df7050"));
    p.setPen(pen);
    p.drawLine(QPoint(xstartPos,10 + baseyPos),QPoint(xstartPos + xWidth,10 + baseyPos));

    pen.setStyle(Qt::SolidLine);
    pen.setColor(QColor("#000000"));
    p.setPen(pen);
    font.setPointSize(8);
    p.setFont(font);

    //xAxis
    p.drawLine(QPoint(xstartPos,ystartPos + yHeight),QPoint(xstartPos + xWidth,ystartPos + yHeight));
    //xAxis Unit
    p.drawText(xstartPos + xWidth + 10,yHeight,50,20,Qt::AlignLeft|Qt::AlignVCenter,m_xAxisUnit);
    //xAxis text
    for (int i = 0; i < xAxisSize + 1; i++)
    {
    
    
        p.drawLine(xstartPos+(xWidth/xAxisSize)*i,yHeight+10,xstartPos+(xWidth/xAxisSize)*i,yHeight+7);
        if (m_chartModel == 1)
        {
    
    
            int timespec = m_timeSpec + xAxisMin+(xAxisMax-xAxisMin)/xAxisSize*i;
            p.drawText(xstartPos+(xWidth/xAxisSize)*i-25,yHeight+10,50,20,Qt::AlignCenter,QDateTime::fromTime_t(timespec).toString("hh:MM:ss"));
        }
        else
            p.drawText(xstartPos+(xWidth/xAxisSize)*i-20,yHeight+10,40,20,Qt::AlignCenter,QString::number(xAxisMin+(xAxisMax-xAxisMin)/xAxisSize*i,'f',0));
    }

    //yAxis
    p.drawLine(QPoint(xstartPos,10),QPoint(xstartPos,ystartPos + yHeight));
    //yAxis Unit
    p.drawText(xstartPos + 5,0,60,20,Qt::AlignLeft|Qt::AlignVCenter,m_yAxisUnit);
    //yAxis text
    for (int i = 0; i < yAxisSize; i++)
    {
    
    
        p.drawLine(xstartPos,ystartPos+(yHeight/yAxisSize)*i,xstartPos + 3,ystartPos+(yHeight/yAxisSize)*i);
        p.drawText(0,ystartPos+(yHeight/yAxisSize)*i-10,xstartPos - 5,20,Qt::AlignRight|Qt::AlignVCenter,QString::number(yAxisMaxVal/yAxisSize*(yAxisSize-i)));
    }
}

void MChartCurve::setxAxisUnit(QString val)
{
    
    
    m_xAxisUnit = val;
}

void MChartCurve::setyAxisUnit(QString val)
{
    
    
    m_yAxisUnit = val;
}

Method 2: Use qcustomplot to implement
bar charts and line charts:
Please add image description
Please add image description

Code:
First, you need to introduce the files qcustomplot.h and qcustomplot.cpp
download address: https://download.csdn.net/download/weixin_43246170/87785302
.h

    QCustomPlot* m_cusPlot = nullptr;
    QCPBars *m_bars = nullptr;
    QVector<double> m_xList;
    QVector<double> m_yList;

.cpp

void SeaChartWidget::creatPlotChart()
{
    
    
    //qcomtomplot
    m_cusPlot = new QCustomPlot();
    m_cusPlot->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectAxes |
                               QCP::iSelectLegend | QCP::iSelectPlottables);
    m_cusPlot->axisRect()->setRangeDrag(Qt::Horizontal);
    m_cusPlot->setFixedSize(660,300);
    //背景透明
    m_cusPlot->setBackground(Qt::transparent);
    m_cusPlot->setStyleSheet("background:transparent");

    //        m_cusPlot->yAxis->setTickLabels(false); //关闭左侧y轴刻度值
    //        m_cusPlot->axisRect()->setupFullAxesBox(); //补全上下边框线

    //y
    m_cusPlot->xAxis->setRange(120, 120, Qt::AlignRight);
    m_cusPlot->yAxis->setRange(1000, 1000, Qt::AlignRight);
    m_cusPlot->yAxis->ticker()->setTickStepStrategy(QCPAxisTicker::TickStepStrategy::customTickCount);
    m_cusPlot->yAxis->ticker()->setTickCount(7);

    //x
    QSharedPointer<QCPAxisTickerDateTime> dateTick(new QCPAxisTickerDateTime);
    dateTick->setDateTimeFormat("hh:mm:ss");
    dateTick->setTickOrigin(6);    //设置第一个刻度值
    m_cusPlot->xAxis->setTicker(dateTick);
    m_cusPlot->xAxis->ticker()->setTickStepStrategy(QCPAxisTicker::TickStepStrategy::customTickCount);
    m_cusPlot->xAxis->ticker()->setTickCount(6);

#if 1 //柱状图
    m_bars = new QCPBars(m_cusPlot->xAxis, m_cusPlot->yAxis);  // 使用xAxis作为柱状图的x轴,yAxis作为y轴
    m_bars->setAntialiased(false); // 为了更好的边框效果,关闭抗齿锯
    m_bars->setPen(QPen(QColor(0, 160, 140).lighter(130))); // 设置柱状图的边框颜色
    m_bars->setBrush(QColor(20,68,106));  // 设置柱状图的画刷颜色

    //隐藏网格
    m_cusPlot->xAxis->grid()->setVisible(false);
    m_cusPlot->yAxis->grid()->setVisible(false);

    //坐标轴箭头
    m_cusPlot->xAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);
    m_cusPlot->yAxis->setUpperEnding(QCPLineEnding::esSpikeArrow);
#endif

    //显示右侧y轴
    //        m_cusPlot->yAxis2->setVisible(true);
    //        m_cusPlot->axisRect()->axis(QCPAxis::atRight, 0)->setRange(1000, 1000, Qt::AlignRight);
    //        m_cusPlot->addGraph(m_cusPlot->xAxis, m_cusPlot->axisRect()->axis(QCPAxis::atRight, 0));
    m_cusPlot->addGraph(m_cusPlot->xAxis);

    m_cusPlot->graph(0)->setPen(QPen(Qt::blue));
    QGraphicsProxyWidget *w = m_mapView->scene()->addWidget(m_cusPlot);
    w->setPos(GraphicsMap::toScene(MyGeoCoordinate(m_lat,m_lon)));
}

void SeaChartWidget::updatePlotData()
{
    
    
    static double index = 0;
    index = index + 2;
    m_xList.append(index);
    m_yList.append(rand()%500);

#if 0 //折线图
    m_cusPlot->graph(0)->setData(m_xList, m_yList);//指定数据
    //        m_cusPlot->graph(0)->rescaleValueAxis(false,true);  //x,y刻度值根据数据实时变化
#else //柱状图
    m_bars->setData(m_xList, m_yList);
    //        m_bars->rescaleValueAxis(false,true);  //x,y刻度值根据数据实时变化
#endif
    //注意需要放在数据后面,否则会出现第一次设置未成功
    m_cusPlot->xAxis->rescale(true);   //true:从右侧开始绘制最新数据;false:从左侧开始绘制最新数据
    m_cusPlot->xAxis->setRange(m_cusPlot->xAxis->range().upper, 120, Qt::AlignRight);
    m_cusPlot->replot();
}

Guess you like

Origin blog.csdn.net/weixin_43246170/article/details/130682848
Recommended