文章目录
前言1.介绍2.效果一、实现(以下代码必要部分都已加注释)1.集成后的CMyChart2.柱状图实现3.饼状图实现4.折线图实现5.曲线图实现二、使用前言
项目源码:传送门
|版本声明:山河君,未经博主允许,禁止转载
1.介绍
Qt图标(Qt Charts)出现晚于QWT、QCustomPlot,界面看起来也很优美,最主要的是要比后两种实现起来方便许多,当然,在自主灵活性上面就差了一点。
QChart已经集成在Qt5.7中,使用时在项目文件中加QT += charts
即可,不过在安装Qt过程中,QChart默认时不勾选的,在安装时需要用户自行勾选。
2.效果
柱状图:可设置标题栏,X轴标题, Y轴标题,柱形颜色,轴刻度,是否显示提示信息(柱形颜色含义)等
饼状图:可设置空心圆、实心圆、点击扇形弹出(信息可编辑)、提示信息(扇形颜色含义)、空心大小比例,图形名称等
折线图:可多条线一起显示、X轴名称、刻度尺,Y轴名称、刻度尺,提示信息,图形名称,X轴为时间轴等
曲线图:可多条线一起显示、X轴名称、刻度尺,Y轴名称、刻度尺,提示信息,图形名称,X轴为时间轴等
一、实现(以下代码必要部分都已加注释)
1.集成后的CMyChart
由于我的负责的项目中,以上四种图形都需要使用,所以使用开闭将这四种集成了一下,如果只使用一种,那么这一部分可以过滤不看,只需要将项目中的文件单独拿出来即可。
调用顺序:GetChartWithType->SetAxisXRange/SetAxisYRange/SetDateTimeAxisX->SetAxisXTitle/SetAxisYTitle->AppendSeries
头文件
#ifndef CMYCHART_H#define CMYCHART_H#include <QObject>#include <QtCharts>QT_CHARTS_USE_NAMESPACEstruct BarDateInfo{QString qsKey;QVector<qreal> vecVal;};class CMyChart : public QObject{Q_OBJECTpublic:enum EType{eInvalid, //无效eBarChart,//柱状图ePieChart,//饼状图eLineChart,//折线图eSplineChart //曲线图};enum EColor{eBlue,//蓝色eGreen, //绿色eYellow, //黄色ePurple, //紫色eRed, //红色eLightBlue,//淡蓝色eLightGreen, //淡绿色eLightYellow, //淡黄色eLightPurple, //淡紫色};public:CMyChart(const CMyChart::EType& type, QChartView* pView, QObject *parent = nullptr);virtual ~CMyChart();public://根据选择的图形,返回CMyChartstatic CMyChart* GetChartWithType(const EType& eType, QChartView* pView);//根据传入颜色转换成QColorQColor toQColor(const EColor& eColor);public://清空界面上显示的图形virtual void ClearGraphical() = 0;//设置提示信息是否显示void SetLegend(bool bLegend = true);//设置标题栏void SetTitle(const QString& qsTitle);//设置X轴坐标、刻度尺,柱状图、饼状图调此接口无用virtual void SetAxisXRange(const qreal& qMin = 0, const qreal& qMax = 10, const int& nTickCount = 5){};//设置Y轴坐标、刻度尺,柱状图、饼状图调此接口无用virtual void SetAxisYRange(const qreal& qMin = 0, const qreal& qMax = 10, const int& nTickCount = 5){};//设置时间坐标轴,柱状图、饼状图调此接口无用virtual void SetDateTimeAxisX(const QDateTime& dtStart,const QDateTime& dtEnd,const QString& qsFormat = "yyyy-MM-dd",const int& nTickCount = 5){};//设置X轴标题,饼状图调此接口无用virtual void SetAxisXTitle(const QString& qsAxisXTitle){};//设置Y轴标题,柱状图调此接口无用virtual void SetAxisYTitle(const QString& qsAxisYTitle){};//柱状图添加一组数据virtual void AppendSeries(const QString& qsAxisXName,QMap<QString, qreal>& mapData,const QVector<EColor>& vecColors = m_vecDefCol){};//饼状图添加数据virtual void AppendSeries(QMap<QString, qreal>& mapData, const QVector<EColor>& vecColors = m_vecDefCol){};//折线图、曲线图添加一条线virtual void AppendSeries(const QString& name, QMap<qreal, qreal> mapVal){};//折线图、曲线图添加坐标轴为时间的一条线virtual void AppendSeries(const QString& name, QMap<QDateTime, qreal> mapVal){};public:EType m_eType;QChart* m_pChart;QChartView* m_pChartView;static QVector<EColor> m_vecDefCol; //默认颜色顺序};#endif // CMYCHART_H
源文件:
#include "CMyChart.h"#include "CMyBarChart.h"#include "CMyPieChart.h"#include "CMyLineChart.h"#include "CMySplineChart.h"QVector<CMyChart::EColor> CMyChart::m_vecDefCol = {eBlue, eGreen, eYellow, ePurple, eRed, eLightBlue, eLightGreen, eLightYellow, eLightPurple};CMyChart::CMyChart(const CMyChart::EType& type, QChartView* pView, QObject *parent): QObject (parent), m_eType(type), m_pChartView(pView){m_pChart = new QChart;m_pChart->setAnimationOptions(QChart::SeriesAnimations);m_pChart->legend()->setVisible(true); //设置提示打开(默认打开)m_pChart->legend()->show();//显示提示m_pChart->layout()->setContentsMargins(0, 0, 0, 0); //设置布局边距m_pChart->setMargins(QMargins(0, 0, 0, 0)); //设置控件边距m_pChart->setBackgroundRoundness(0); //保存图表背景角上的圆角的直径。m_pChartView->setChart(m_pChart);m_pChartView->setRenderHint(QPainter::Antialiasing); //防图形走样}CMyChart::~CMyChart(){}CMyChart* CMyChart::GetChartWithType(const EType &eType, QChartView *pView){if(pView == NULL)return NULL;switch (eType){case eInvalid:return NULL;case eBarChart:return new CMyBarChart(eType, pView);case ePieChart:return new CMyPieChart(eType, pView);case eLineChart:return new CMyLineChart(eType, pView);case eSplineChart:return new CMySplineChart(eType, pView);default:return NULL;}}QColor CMyChart::toQColor(const EColor &eColor){switch (eColor){case eBlue:return QColor(0, 122, 255);case eGreen:return QColor(27, 201, 133);case eYellow:return QColor(255,168, 0);case ePurple:return QColor(37, 217, 255);case eRed:return QColor(252, 79, 76);case eLightBlue:return QColor(104, 153, 255);case eLightGreen:return QColor(37, 217, 255);case eLightYellow:return QColor(255, 211, 35);case eLightPurple:return QColor(212, 139, 250);default:return QColor(0, 122, 255);}}void CMyChart::SetLegend(bool bLegend){if(bLegend)m_pChart->legend()->show();elsem_pChart->legend()->hide();}void CMyChart::SetTitle(const QString &qsTitle){m_pChart->setTitle(qsTitle);}
2.柱状图实现
头文件:
#ifndef CMYBARCHART_H#define CMYBARCHART_H#include <QObject>#include "CMyChart.h"class CMyBarChart : public CMyChart{Q_OBJECTpublic:explicit CMyBarChart(const CMyChart::EType& type, QChartView* pView, QObject *parent = nullptr);virtual ~CMyBarChart();public:virtual void ClearGraphical();virtual void SetAxisXTitle(const QString& qsAxisXTitle);virtual void SetAxisYTitle(const QString& qsAxisYTitle);virtual void SetAxisYRange(const qreal& qMin = 0, const qreal& qMax = 10, const int& nTickCount = 5);virtual void AppendSeries(const QString& qsAxisXName,QMap<QString, qreal>& mapData,const QVector<EColor>& vecColors = m_vecDefCol);private:QValueAxis* m_pBarAxisY;QBarSeries* m_pBarSeries;QVector<QBarSet*> m_vecBarSet;QBarCategoryAxis* m_pBarAxisX;};#endif // CMYBARCHART_H
源文件
#include "CMyBarChart.h"CMyBarChart::CMyBarChart(const CMyChart::EType& type, QChartView* pView, QObject *parent): CMyChart(type, pView, parent){m_pBarSeries = new QBarSeries;//创建分组系列m_pBarSeries->setLabelsVisible(true); //设置显示柱形图值m_pBarSeries->setLabelsPosition(QAbstractBarSeries::LabelsInsideEnd); //设置值位置m_pChart->addSeries(m_pBarSeries);//将分组放入chart容器m_pChart->createDefaultAxes();//创建默认坐标轴m_pChart->legend()->setAlignment(Qt::AlignBottom); //设置提示说明位置m_vecBarSet.fill(NULL, 10);//默认最多只能有10个柱子}CMyBarChart::~CMyBarChart(){delete m_pBarSeries;delete m_pBarAxisX;delete m_pBarAxisY;}void CMyBarChart::ClearGraphical(){for(QVector<QBarSet*>::iterator it = m_vecBarSet.begin(); it != m_vecBarSet.end(); it++){if(*it != NULL)delete *it;}m_vecBarSet.fill(NULL, 10); //默认最多只有10种类型的柱子m_pBarAxisX->clear();m_pBarSeries->clear();}void CMyBarChart::SetAxisXTitle(const QString &qsAxisXTitle){m_pBarAxisX->setTitleText(qsAxisXTitle);}void CMyBarChart::SetAxisYTitle(const QString &qsAxisYTitle){m_pBarAxisY->setTitleText(qsAxisYTitle);}void CMyBarChart::SetAxisYRange(const qreal& qMin, const qreal& qMax, const int& nTickCount){m_pBarAxisX = new QBarCategoryAxis;//创建X轴m_pBarAxisY = new QValueAxis; //创建Y轴m_pBarAxisX->setLabelsAngle(-45); //设置X轴坐标倾斜m_pBarAxisY->setGridLineVisible(false); //设置网格不可见m_pBarAxisY->setRange(qMin, qMax);m_pBarAxisY->setTickCount(nTickCount);m_pChart->setAxisX(m_pBarAxisX, m_pBarSeries); //将X坐标轴和分组进行统一m_pChart->setAxisY(m_pBarAxisY, m_pBarSeries); //将Y坐标轴和分组进行统一}/** 一个QBarSet代表的是同一颜色的柱形,里面存放多个柱子的值* 此接口先将一组数据作为柱子类型数的最大大小,然后根据先后顺序给柱子添加数据*/void CMyBarChart::AppendSeries(const QString &qsAxisXName, QMap<QString, qreal>& mapData, const QVector<EColor> &vecColors){QMap<QString, qreal>::iterator it = mapData.begin();for(int i = 0; i < mapData.size(); i++){if(m_vecBarSet[i] == NULL){m_vecBarSet[i] = new QBarSet(it.key());m_vecBarSet[i]->setColor(toQColor(vecColors[i]));}m_vecBarSet[i]->append(it.value());m_pBarSeries->append(m_vecBarSet[i]);it++;}m_pBarAxisX->append(qsAxisXName);}
3.饼状图实现
头文件
#ifndef CMYPIECHART_H#define CMYPIECHART_H#include <QObject>#include "CMyChart.h"class CMyPieChart : public CMyChart{Q_OBJECTpublic:explicit CMyPieChart(const CMyChart::EType& type, QChartView* pView, QObject *parent = nullptr);virtual ~CMyPieChart();public:virtual void ClearGraphical();virtual void AppendSeries(QMap<QString, qreal>& mapData, const QVector<EColor>& vecColors = m_vecDefCol);private slots://点击扇形槽函数void ClickedSector(QPieSlice* pSlice);private:QPieSeries* m_pPieSeries;};#endif // CMYPIECHART_H
源文件
#include "CMyPieChart.h"CMyPieChart::CMyPieChart(const CMyChart::EType& type, QChartView* pView, QObject *parent): CMyChart(type, pView, parent){m_pPieSeries = new QPieSeries;m_pPieSeries->setHoleSize(0.5);//设置空心占比m_pPieSeries->setPieSize(0.8);//设置圆形占比m_pChart->addSeries(m_pPieSeries); //将饼图放入容器m_pChart->legend()->setAlignment(Qt::AlignRight); //设置提示说明位置connect(m_pPieSeries, SIGNAL(clicked(QPieSlice*)), this, SLOT(ClickedSector(QPieSlice*))); //点击扇形}CMyPieChart::~CMyPieChart(){delete m_pPieSeries;}void CMyPieChart::ClearGraphical(){m_pPieSeries->clear();}void CMyPieChart::ClickedSector(QPieSlice* pSlice){if(pSlice->isExploded()) //判断扇形有没有弹出{pSlice->setExploded(false);pSlice->setLabelVisible(false);}else {pSlice->setExploded(true);//设置扇形弹出pSlice->setLabelVisible(true); //设置扇形提示}}void CMyPieChart::AppendSeries(QMap<QString, qreal> &mapData, const QVector<EColor> &vecColors){m_pPieSeries->clear();QMap<QString, qreal>::iterator it = mapData.begin();for(int i = 0; i < mapData.size(); i++){QPieSlice* pSlice = new QPieSlice(it.key(), it.value());pSlice->setLabel(it.key());pSlice->setColor(toQColor(vecColors[i]));m_pPieSeries->append(pSlice);it++;}}
4.折线图实现
头文件
#ifndef CMYLINECHART_H#define CMYLINECHART_H#include <QObject>#include "CMyChart.h"class CMyLineChart : public CMyChart{Q_OBJECTpublic:explicit CMyLineChart(const CMyChart::EType& type, QChartView* pView, QObject *parent = nullptr);~CMyLineChart();public:virtual void ClearGraphical();virtual void SetAxisXRange(const qreal& qMin = 0, const qreal& qMax = 10, const int& nTickCount = 5);virtual void SetAxisYRange(const qreal& qMin = 0, const qreal& qMax = 10, const int& nTickCount = 5);virtual void SetAxisXTitle(const QString& qsAxisXTitle);virtual void SetAxisYTitle(const QString& qsAxisYTitle);virtual void SetDateTimeAxisX(const QDateTime& dtStart,const QDateTime& dtEnd,const QString& qsFormat = "yyyy-MM-dd",const int& nTickCount = 5);virtual void AppendSeries(const QString& name, QMap<qreal, qreal> mapVal);virtual void AppendSeries(const QString& name, QMap<QDateTime, qreal> mapVal);private:boolm_bIsDateTime;QValueAxis* m_pLineAxisX;QValueAxis* m_pLineAxisY;QDateTimeAxis*m_pAxisDateTime;QVector<QLineSeries*> m_vecLineSeries;};#endif // CMYLINECHART_H
源文件
#include "CMyLineChart.h"CMyLineChart::CMyLineChart(const CMyChart::EType& type, QChartView* pView, QObject *parent): CMyChart(type, pView, parent){m_bIsDateTime = false;}CMyLineChart::~CMyLineChart(){for(QVector<QLineSeries*>::iterator it = m_vecLineSeries.begin(); it != m_vecLineSeries.end(); it++)delete *it;}void CMyLineChart::ClearGraphical(){for(QVector<QLineSeries*>::iterator it = m_vecLineSeries.begin(); it != m_vecLineSeries.end(); it++)delete *it;m_vecLineSeries.clear();}void CMyLineChart::SetAxisXRange(const qreal &qMin, const qreal &qMax, const int &nTickCount){m_pLineAxisX = new QValueAxis;m_pLineAxisX->setRange(qMin, qMax);m_pLineAxisX->setTickCount(nTickCount);m_pChart->addAxis(m_pLineAxisX, Qt::AlignBottom);}void CMyLineChart::SetAxisYRange(const qreal &qMin, const qreal &qMax, const int &nTickCount){m_pLineAxisY = new QValueAxis;m_pLineAxisY->setRange(qMin, qMax);m_pLineAxisY->setTickCount(nTickCount);m_pLineAxisY->setGridLineVisible(false);m_pChart->addAxis(m_pLineAxisY, Qt::AlignLeft);}void CMyLineChart::SetDateTimeAxisX(const QDateTime &dtStart, const QDateTime &dtEnd, const QString &qsFormat, const int &nTickCount){m_bIsDateTime = true;m_pAxisDateTime = new QDateTimeAxis;m_pAxisDateTime->setFormat(qsFormat);m_pAxisDateTime->setRange(dtStart, dtEnd);m_pAxisDateTime->setTickCount(nTickCount);m_pChart->addAxis(m_pAxisDateTime, Qt::AlignBottom);}void CMyLineChart::SetAxisXTitle(const QString &qsAxisXTitle){if(m_bIsDateTime)m_pAxisDateTime->setTitleText(qsAxisXTitle);elsem_pLineAxisX->setTitleText(qsAxisXTitle);}void CMyLineChart::SetAxisYTitle(const QString &qsAxisYTitle){m_pLineAxisY->setTitleText(qsAxisYTitle);}void CMyLineChart::AppendSeries(const QString &name , QMap<qreal, qreal> mapVal){QLineSeries* pLineSeries = new QLineSeries;pLineSeries->setName(name);pLineSeries->setPointsVisible(true);pLineSeries->setPointLabelsVisible(true); //设置显示点位m_pChart->addSeries(pLineSeries);for(QMap<qreal, qreal>::iterator it = mapVal.begin(); it != mapVal.end(); it++)pLineSeries->append(it.key(), it.value());m_vecLineSeries.push_back(pLineSeries);pLineSeries->attachAxis(m_pLineAxisX);pLineSeries->attachAxis(m_pLineAxisY);}void CMyLineChart::AppendSeries(const QString &name, QMap<QDateTime, qreal> mapVal){QLineSeries* pLineSeries = new QLineSeries;pLineSeries->setName(name);pLineSeries->setPointsVisible(true);pLineSeries->setPointLabelsVisible(false); //设置显示点位m_pChart->addSeries(pLineSeries);for(QMap<QDateTime, qreal>::iterator it = mapVal.begin(); it != mapVal.end(); it++)pLineSeries->append(it.key().toMSecsSinceEpoch(), it.value());m_vecLineSeries.push_back(pLineSeries);pLineSeries->attachAxis(m_pAxisDateTime);pLineSeries->attachAxis(m_pLineAxisY);}
5.曲线图实现
头文件
#ifndef CMYSPLINECHART_H#define CMYSPLINECHART_H#include <QObject>#include "CMyChart.h"class CMySplineChart : public CMyChart{Q_OBJECTpublic:explicit CMySplineChart(const CMyChart::EType& type, QChartView* pView, QObject *parent = nullptr);~CMySplineChart();public:virtual void ClearGraphical();virtual void SetAxisXRange(const qreal& qMin = 0, const qreal& qMax = 10, const int& nTickCount = 5);virtual void SetAxisYRange(const qreal& qMin = 0, const qreal& qMax = 10, const int& nTickCount = 5);virtual void SetAxisXTitle(const QString& qsAxisXTitle);virtual void SetAxisYTitle(const QString& qsAxisYTitle);virtual void SetDateTimeAxisX(const QDateTime& dtStart,const QDateTime& dtEnd,const QString& qsFormat = "yyyy-MM-dd",const int& nTickCount = 5);virtual void AppendSeries(const QString& name, QMap<qreal, qreal> mapVal);virtual void AppendSeries(const QString& name, QMap<QDateTime, qreal> mapVal);signals:public slots:private:bool m_bIsDateTime;QValueAxis* m_pLineAxisX;QValueAxis* m_pLineAxisY;QDateTimeAxis* m_pAxisDateTime;QVector<QSplineSeries*>m_vecSplineSeries;};#endif // CMYSPLINECHART_H
源文件
#include "CMySplineChart.h"CMySplineChart::CMySplineChart(const CMyChart::EType& type, QChartView* pView, QObject *parent): CMyChart(type, pView, parent){m_bIsDateTime = false;}CMySplineChart::~CMySplineChart(){for(QVector<QSplineSeries*>::iterator it = m_vecSplineSeries.begin(); it != m_vecSplineSeries.end(); it++)delete *it;}void CMySplineChart::ClearGraphical(){for(QVector<QSplineSeries*>::iterator it = m_vecSplineSeries.begin(); it != m_vecSplineSeries.end(); it++)delete *it;m_vecSplineSeries.clear();}void CMySplineChart::SetAxisXRange(const qreal &qMin, const qreal &qMax, const int &nTickCount){m_pLineAxisX = new QValueAxis;m_pLineAxisX->setRange(qMin, qMax);m_pLineAxisX->setTickCount(nTickCount);m_pChart->addAxis(m_pLineAxisX, Qt::AlignBottom);}void CMySplineChart::SetAxisYRange(const qreal &qMin, const qreal &qMax, const int &nTickCount){m_pLineAxisY = new QValueAxis;m_pLineAxisY->setRange(qMin, qMax);m_pLineAxisY->setTickCount(nTickCount);m_pLineAxisY->setGridLineVisible(false);m_pChart->addAxis(m_pLineAxisY, Qt::AlignLeft);}void CMySplineChart::SetDateTimeAxisX(const QDateTime &dtStart, const QDateTime &dtEnd, const QString &qsFormat, const int &nTickCount){m_bIsDateTime = true;m_pAxisDateTime = new QDateTimeAxis;m_pAxisDateTime->setFormat(qsFormat);m_pAxisDateTime->setRange(dtStart, dtEnd);m_pAxisDateTime->setTickCount(nTickCount);m_pChart->addAxis(m_pAxisDateTime, Qt::AlignBottom);}void CMySplineChart::SetAxisXTitle(const QString &qsAxisXTitle){if(m_bIsDateTime)m_pAxisDateTime->setTitleText(qsAxisXTitle);elsem_pLineAxisX->setTitleText(qsAxisXTitle);}void CMySplineChart::SetAxisYTitle(const QString &qsAxisYTitle){m_pLineAxisY->setTitleText(qsAxisYTitle);}void CMySplineChart::AppendSeries(const QString &name , QMap<qreal, qreal> mapVal){QSplineSeries* pSplineSeries = new QSplineSeries;pSplineSeries->setName(name);pSplineSeries->setPointsVisible(true);pSplineSeries->setPointLabelsVisible(true); //设置显示点位m_pChart->addSeries(pSplineSeries);for(QMap<qreal, qreal>::iterator it = mapVal.begin(); it != mapVal.end(); it++)pSplineSeries->append(it.key(), it.value());m_vecSplineSeries.push_back(pSplineSeries);pSplineSeries->attachAxis(m_pLineAxisX);pSplineSeries->attachAxis(m_pLineAxisY);}void CMySplineChart::AppendSeries(const QString &name, QMap<QDateTime, qreal> mapVal){QSplineSeries* pSplineSeries = new QSplineSeries;pSplineSeries->setName(name);pSplineSeries->setPointsVisible(true);pSplineSeries->setPointLabelsVisible(false); //设置显示点位m_pChart->addSeries(pSplineSeries);for(QMap<QDateTime, qreal>::iterator it = mapVal.begin(); it != mapVal.end(); it++)pSplineSeries->append(it.key().toMSecsSinceEpoch(), it.value());m_vecSplineSeries.push_back(pSplineSeries);pSplineSeries->attachAxis(m_pAxisDateTime);pSplineSeries->attachAxis(m_pLineAxisY);}
二、使用
使用QChart需要对于widget进行提升
项目源码:传送门
码字不易,各位观众老爷,如果觉得有点用,还请点个赞,让我涨涨积分哈!