QT自定义控件折线图、趋势图。

这里提供两种实现方式,一直自绘的自定义控件,一直三方SDK(qcustomplot)。
这里主要介绍自绘的,它的优点是结构简单,代码逻辑好修改,容易定制,缺点是功能相对单一。三方的qcustomplot优点是功能丰富,性能突出。缺点是代码结构复杂,难以根据实际需求快速定制。

QT自定义控件折线图、趋势图。_第1张图片
QT自定义控件折线图、趋势图。_第2张图片

QT自定义控件折线图、趋势图。_第3张图片
QT自定义控件折线图、趋势图。_第4张图片
QT自定义控件折线图、趋势图。_第5张图片

方法一:
接口介绍:

//传入数据,根据实际情况添加。
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 &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轴范围

调用接口:

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

实现代码:
.h

#ifndef MCHARTCURVE_H
#define MCHARTCURVE_H

#include 
#include 

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 
#include 
#include 

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;
}

方法二:使用qcustomplot实现
柱状图和折线图:

代码:
首先需要引入文件qcustomplot.h和qcustomplot.cpp
下载地址: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();
}

你可能感兴趣的:(QT,qt,c++,c语言)