Qt—QChart动态绘图(折现图、曲线图、柱状图、饼图)工厂 V 1.0

本文介绍使用Qt QChart库动态绘制多种图表的方法,包括折线图、曲线图、柱状图和饼图。通过继承和封装,实现了图表的动态刷新和数据更新,提供了基类和派生类的详细实现,以及如何实例化和调用这些图表。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前提

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

优缺点

结论:无脑封装一时爽,一直封装一直爽
优点:调用快递代码少;可以快速维护新的图表;爽
缺点:个种图表样式很难维护;数据是假的,来真的时候要做修改

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值