Qt—QChart动态绘图(折现图、曲线图、柱状图、饼图)工厂 V 1.0
前提
在Qt Qchart的机制里,实现一个图标的流程为Chart -> Axis -> Series -> ChartView
分别是:
- 实例图标引擎
- 实例坐标轴
- 实例数据类型(图标类型)
- 显示图表
目的
实现一个Demo,可以显示曲线图、柱状图等并可以动态刷新数据反馈到图形显示上
类图
Ax表示坐标轴,Date是数据,m_Title为图标的标题
Demo
(整个图标都是动态刷新的,没有工具所以截取不了GIF)
基类说明
成员参数
QChart *m_chart; 【图标】
QChartView *m_chartView; 【图标展示框指】
QValueAxis *m_axisX; 【x轴】
QValueAxis *m_axisY; 【y轴】
QString m_Title; 【图标标题】
QString m_XTitle; 【x轴标题】
QString m_YTitle; 【y轴标题】
QString m_XText; 【x轴刻度】
QString m_YText; 【y轴刻度】
成员函数
QChartView * getView();
-【输出当前图标的窗体】
virtual void InitAx();
-【初始化坐标轴,在实例不同的图表时,主要改的就是这个,在基类中实现的时通用的xy的坐标轴,这在线形图会有用,柱状图饼图等将无用】
virtual void InitDate();
-【用于初始化需要加载的数据,在不同的图标中需要用到的数据是不同,大多数有自己特定的Qt类来存放数据,如柱状图的QBarSet】
virtual void refreshDate();
-【设置为虚函数的原因同上,各种图表都有自己的特色】
virtual void refreshAx();
-【基类只是调用库函数update(),在派生类中,在此之前要运行各自的refreshDate()来刷新数据】
void refrshAx(int minX, int minY, int maxX, int maxY);
-【刷新xy轴的刻度值,主要适用线性图,用于轴刻度的动态刷新】
void setTitlrText(QString &title);
-【用于设置图标的名字】
void setAxisX(QString &XTitle, QString &XText);
-【设置x轴的名字和刻度】
void setAxisY(QString &YTitle, QString &YText);
-【设置y轴的名字和刻度】
基类的实现
MyChart.h
#include <QChart>
#include <QChartView>
#include <QValueAxis>
#include <QString>
#include <QTimer>
QT_CHARTS_USE_NAMESPACE
#define F2 "%.2f"
#define D "%d"
#define G "%.2g"
class MyQChart:public QWidget
{
public:
MyQChart();
virtual ~MyQChart();
QChartView * getView();
virtual void InitAx(); //初始化坐标轴
virtual void InitDate(); //初始化数据
virtual void refreshDate(); //刷新数据
virtual void refreshAx(); //刷新坐标轴
void refrshAx(int minX, int minY, int maxX, int maxY); //刷新坐标轴刻度
void setTitlrText(QString &title);
void setAxisX(QString &XTitle, QString &XText);
void setAxisY(QString &YTitle, QString &YText);
QChart *m_chart;
QChartView *m_chartView;
QValueAxis *m_axisX;
QValueAxis *m_axisY;
QString m_Title;
QString m_XTitle;
QString m_YTitle;
QString m_XText;
QString m_YText;
};
MyChart.cpp
MyQChart::MyQChart()
{
m_chart = new QChart;
m_chartView = new QChartView(m_chart);
m_Title = "";
m_XTitle = "";
m_YTitle = "";
m_XText = G;
m_YText = G;
}
MyQChart::~MyQChart()
{
delete m_chart;
delete m_chartView;
}
void MyQChart::InitAx()
{
InitDate();
//建立坐标轴
m_axisX = new QValueAxis;
//m_axisX->setRange(0, 20); //设置范围
m_axisX->setLabelFormat(m_XText); //设置刻度格式
//m_axisX->setGridLineVisible(false); //网格不可见
//m_axisX->setTickCount(10);
//m_axisX->setMinorTickCount(1);
m_axisX->setTitleText(m_XTitle); //描述
m_axisY = new QValueAxis;
//m_axisY->setRange(0, 10); //设置范围
m_axisY->setLabelFormat(m_YText); //设置刻度格式
//m_axisY->setGridLineVisible(false); //网格不可见
//m_axisY->setTickCount(10);
//m_axisY->setMinorTickCount(1);
m_axisY->setTitleText(m_YTitle); //描述
m_chart->addAxis(m_axisX, Qt::AlignBottom); //下Qt::AlignBottom 上Qt::AlignTop
m_chart->addAxis(m_axisY, Qt::AlignLeft); //左 Qt::AlignLeft 右 Qt::AlignRight
m_chart->setTitle(m_Title);
m_chart->setAnimationOptions(QChart::SeriesAnimations);
m_chart->legend()->hide();
//m_chartView->chart()->addSeries(series);
//m_chart->setAxisX(m_axisX, series);
//m_chart->setAxisY(m_axisY, series);
}
void MyQChart::InitDate()
{
;
}
void MyQChart::refreshDate()
{
;
}
void MyQChart::refreshAx()
{
m_chartView->chart()->update();
}
void MyQChart::setTitlrText(QString &title)
{
m_Title = title;
}
void MyQChart::setAxisX(QString& XTitle, QString& XText)
{
m_XTitle = XTitle;
m_XText = XText;
}
void MyQChart::setAxisY(QString& YTitle, QString& YText)
{
m_YTitle = YTitle;
m_YText = YText;
}
QChartView * MyQChart::getView()
{
return m_chartView;
}
void MyQChart::refrshAx(int minX, int minY, int maxX, int maxY)
{
m_axisX->setRange(minX, maxX);
m_axisY->setRange(minY, maxY);
}
派生类
柱状图
MyQChartBar.h
#include <QBarSet>
#include <QBarSeries>
#include <QBarCategoryAxis>
#include "MyQChart.h"
class MyQChartBar :
public MyQChart
{
public:
MyQChartBar();
virtual ~MyQChartBar();
virtual void InitAx(); //初始化坐标轴
virtual void InitDate(); //初始化数据
virtual void refreshDate(); //刷新数据
virtual void refreshAx(); //刷新坐标轴
int i; //test val;
private:
QBarSet * set0; //...
QBarSet * set1; //...
QBarSet * set2; //...
QBarSet * set3; //...
QBarSet * set4; //...
QStringList str;
QBarSeries * series;
};
MyQChartBar.cpp
#include "MyQChartBar.h"
#include <QDebug>
MyQChartBar::MyQChartBar()
{
set0 = new QBarSet("Jane");
set1 = new QBarSet("Jone");
set2 = new QBarSet("Mary");
set3 = new QBarSet("Alsex");
set4 = new QBarSet("Summer");
series = new QBarSeries();
}
MyQChartBar::~MyQChartBar()
{
delete set0;
delete set1;
delete set2;
delete set3;
delete set4;
delete series;
}
void MyQChartBar::InitDate()
{
i = 0;
*set0 << 1 << 2 << 3 << 4 << 10;
*set1 << 2 << 3 << 4 << 10 << 4;
*set2 << 3 << 4 << 10 << 4 << 3;
*set3 << 4 << 10 << 4 << 3 << 2;
*set4 << 10 << 4 << 3 << 2 << 1;
series->append(set0);
series->append(set1);
series->append(set2);
series->append(set3);
series->append(set4);
str << "Jan" << "Fed" << "Mar" << "Apr" << "Jun";
}
void MyQChartBar::InitAx()
{
InitDate();
m_chart->addSeries(series);
m_chart->setTitle(m_Title);
m_chart->setAnimationOptions(QChart::SeriesAnimations);
QBarCategoryAxis * axisx = new QBarCategoryAxis();
axisx->append(str);
m_chart->createDefaultAxes();
m_chart->setAxisX(axisx);
m_chart->legend()->setVisible(true); //设置图例为显示状态
m_chart->legend()->setAlignment(Qt::AlignBottom); //设置图例的显示位置在底部
m_chartView->setRenderHints(QPainter::Antialiasing); //抗锯齿
}
void MyQChartBar::refreshDate()
{
i++;
if (i >= 10) i = 0;
qDebug() << i << "updere !!";
//修改数据
set0->remove(0);
set0->insert(0, i);
set0->remove(2);
set0->insert(2, i);
m_chartView->chart()->update();
}
void MyQChartBar::refreshAx()
{
refreshDate();
MyQChart::refreshAx();
}
饼状图
MyQChartPie.h
#include "MyQChart.h"
#include <QPieSeries>
#include <QPieSlice>
class MyQChartPie :
public MyQChart
{
public:
MyQChartPie();
virtual ~MyQChartPie();
virtual void InitAx(); //初始化坐标轴
virtual void InitDate(); //初始化数据
virtual void refreshDate(); //刷新数据
virtual void refreshAx(); //刷新坐标轴;
private:
int i;
QPieSlice *m_slice0;
QPieSlice *m_slice1;
QPieSlice *m_slice2;
//....
QPieSeries *series;
};
MyQChartPie.cpp
#include "MyQChartPie.h"
MyQChartPie::MyQChartPie()
{
series = new QPieSeries();
}
MyQChartPie::~MyQChartPie()
{
delete series;
}
void MyQChartPie::InitAx()
{
InitDate();
m_chart->addSeries(series);
m_chart->setTitle(m_Title);
m_chartView->setRenderHint(QPainter::Antialiasing);
}
void MyQChartPie::InitDate()
{
i = 0;
m_slice0 = new QPieSlice("text1", 1);
m_slice1 = new QPieSlice("text2", 2);
m_slice2 = new QPieSlice("text3", 3);
//...
QList<QPieSlice*> sliceList ;
sliceList << m_slice0 << m_slice1 << m_slice2;
series->append(sliceList);
series->setLabelsVisible();
//m_slice0 = series->slices().at(0);
}
void MyQChartPie::refreshDate()
{
i++;
if (i >= 10) i = 0;
m_slice0->setValue(i);
}
void MyQChartPie::refreshAx()
{
refreshDate();
MyQChart::refreshAx();
}
折线图
MyQChartLine.h
#include "MyQChart.h"
#include <QLineSeries>
class MyQChartLine :
public MyQChart
{
public:
MyQChartLine();
virtual ~MyQChartLine();
virtual void InitAx(); //初始化坐标轴
virtual void InitDate(); //初始化数据
virtual void refreshDate(); //刷新数据
virtual void refreshAx(); //刷新坐标轴
template <typename A_Val, typename B_Val>void addDate(A_Val valX, B_Val valY);
private:
int i;
QLineSeries* series;
};
template <typename A_Val, typename B_Val>
void MyQChartLine::addDate(A_Val valX, B_Val valY)
{
series->append(valX, valY);
m_chartView->chart()->update();
}
MyQChartLine.cpp
#include "MyQChartLine.h"
MyQChartLine::MyQChartLine()
{
series = new QLineSeries();
}
MyQChartLine::~MyQChartLine()
{
delete series;
}
void MyQChartLine::InitAx()
{
MyQChart::InitAx();
m_chartView->chart()->addSeries(series);
m_chart->setAxisX(m_axisX, series);
m_chart->setAxisY(m_axisY, series);
}
void MyQChartLine::InitDate()
{
i = 0;
}
void MyQChartLine::refreshDate()
{
i++;
}
void MyQChartLine::refreshAx()
{
refreshDate();
addDate<int, float>(i, float(i) / 2); //曲线图刷新
if (i <= 20)
{
MyQChart::refrshAx(0, 0, i, (i + 1) / 2);
}
else {
MyQChart::refrshAx(i - 20, ((i + 1) / 2) - 10, i, (i + 1) / 2);
}
}
曲线图
MyQChartSpline.h
#include <QSplineSeries>
#include "MyQChart.h"
class MyQChartSpline :
public MyQChart
{
public:
MyQChartSpline();
virtual ~MyQChartSpline();
virtual void InitAx(); //初始化坐标轴
virtual void InitDate(); //初始化数据
virtual void refreshDate(); //刷新数据
virtual void refreshAx(); //刷新坐标轴
template <typename A_Val, typename B_Val>void addDate(A_Val valX, B_Val valY);
private:
int i; //test date
QSplineSeries* series;
};
template <typename A_Val, typename B_Val>
void MyQChartSpline::addDate(A_Val valX, B_Val valY)
{
series->append(valX, valY);
m_chartView->chart()->update();
}
MyQChartSpline.cpp
#include "MyQChartSpline.h"
MyQChartSpline::MyQChartSpline()
{
series = new QSplineSeries();
}
MyQChartSpline::~MyQChartSpline()
{
delete series;
}
void MyQChartSpline::InitAx()
{
MyQChart::InitAx();
m_chartView->chart()->addSeries(series);
m_chart->setAxisX(m_axisX, series);
m_chart->setAxisY(m_axisY, series);
}
void MyQChartSpline::InitDate()
{
i = 0;
}
void MyQChartSpline::refreshDate()
{
i++;
}
void MyQChartSpline::refreshAx()
{
refreshDate();
addDate<int, float>(i, float(i) * float(i)); //曲线图刷新
if (i <= 20)
{
MyQChart::refrshAx(0, 0, i, (i + 1)*(i + 1));
}
else {
MyQChart::refrshAx(0, 0, i, (i + 1)*(i + 1) / 2);
}
}
如何实例这些图表调用
#include "ui_QtAboutChaat.h"
#include <QLineSeries>
#include <QVBoxlayout>
#include <QHBoxlayout>
#include <QValueAxis>
#include <QTimer>
#include <QString>
#include "MyQChartSpline.h"
#include "MyQChartLine.h"
#include "MyQChartBar.h"
#include "MyQChartPie.h"
QT_CHARTS_USE_NAMESPACE
class QtAboutChaat : public QMainWindow
{
Q_OBJECT
public:
QtAboutChaat(QWidget *parent = Q_NULLPTR);
void InitLayout();
void SetTimer(const int mdelay); //设置定时时间(ms)
//template <typename A_Val> void refreshDate(A_Val valX, A_Val valY, A_Val incrementX, const int num);
public slots:
void slotsTimerDeal();
private:
Ui::QtAboutChaatClass ui;
//QChart *m_chart;
//QChartView *m_chartView;
MyQChartBar *m_Mychart;
MyQChartLine *m_Mychart1;
MyQChartPie *m_Mychart2;
MyQChartSpline *m_Mychart3;
QLineSeries *series;
QVBoxLayout *m_layout;
QHBoxLayout *m_hlayout1;
QHBoxLayout *m_hlayout2;
QValueAxis *m_axisX;
QValueAxis *m_axisY;
QTimer *timer;
QWidget *widget;
};
如何调用
#include "QtAboutChaat.h"
#include <QDebug>
QtAboutChaat::QtAboutChaat(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
m_Mychart = new MyQChartBar;
m_Mychart1 = new MyQChartLine;
m_Mychart2 = new MyQChartPie;
m_Mychart3 = new MyQChartSpline;
InitLayout();
m_Mychart->InitAx();
m_Mychart1->InitAx();
m_Mychart2->InitAx();
m_Mychart3->InitAx();
SetTimer(1000);
}
void QtAboutChaat::SetTimer(const int mdelay)
{
timer = NULL;
timer = new QTimer();
timer->setInterval(mdelay);
connect(timer, SIGNAL(timeout()), this, SLOT(slotsTimerDeal()));
timer->start();
}
void QtAboutChaat::InitLayout()
{
//指针置空
widget = NULL;
m_layout = NULL;
//在mainWindow中加入widget,展示
widget = new QWidget();
this->setCentralWidget(widget);
m_layout = new QVBoxLayout();
m_hlayout1 = new QHBoxLayout();
m_hlayout2 = new QHBoxLayout();
m_Mychart->setTitlrText(QString("test1"));
m_Mychart1->setTitlrText(QString("test2"));
m_Mychart2->setTitlrText(QString("test3"));
m_Mychart3->setTitlrText(QString("test4"));
m_hlayout1->addWidget(m_Mychart->getView());
m_hlayout1->addWidget(m_Mychart1->getView());
m_hlayout2->addWidget(m_Mychart2->getView());
m_hlayout2->addWidget(m_Mychart3->getView());
m_layout->addLayout(m_hlayout1);
m_layout->addLayout(m_hlayout2);
//m_layout->addWidget(m_Mychart->getView());
centralWidget()->setLayout(m_layout);
}
void QtAboutChaat::slotsTimerDeal()
{
//qDebug() << i <<"up date!!";
m_Mychart1->refreshAx(); //曲线图刷新
m_Mychart->refreshAx(); //柱状图刷新
m_Mychart2->refreshAx(); //饼状图刷新
m_Mychart3->refreshAx();
//m_Mychart->m_axisX->setRange(0, i);
//m_Mychart->m_axisY->setRange(0, i);
}
优缺点
结论:无脑封装一时爽,一直封装一直爽
优点:调用快递代码少;可以快速维护新的图表;爽
缺点:个种图表样式很难维护;数据是假的,来真的时候要做修改