Qt自己封装的基于QPainter的饼图类,可自由缩放,实时绘图

1、继承QWidget创建一个hnPieChart类,头文件如下:

#ifndef HNPIECHART_H
#define HNPIECHART_H

#include <QWidget>
#include "ui_hnPieChart.h"

class hnPieChart : public QWidget
{
	Q_OBJECT

public:
	hnPieChart(QWidget *parent = 0);
	~hnPieChart();

public:
	void ClearPieChart();//清除饼图
	void SetChartTitle(const QString& titleName,QFont titleFont,QColor titleColor);//设置饼图标题名称、字体、颜色
	void AddComponentToChart(const QString& name, int Num, QColor color,QFont legendFont,QColor legendColor);//设置饼图组成部分的名称、数量、颜色以及图例的字体、颜色。

private:
	void paintEvent(QPaintEvent *event);//重载虚函数,实时重绘
	void CalculatePercentage();//计算各组成部分的百分比

public slots:
	void DrawPieChart();//绘制饼图的函数

private:
	Ui::hnPieChart ui;

	int m_NumOfComponent;//饼图组成部分的数量

	QVector<QString> m_componentNameVec;//饼图组成部分的的名称
	QVector<int>     m_componentNumberVec;//饼图组成部分的数量
	QVector<QColor>  m_componentColorVec;//饼图组成部分的颜色
	QVector<double>  m_componentPercentageVec;//饼图组成部分所占的百分比,由组成数量计算得来
	QVector<QFont>   m_componentLegendFontVec;//饼图图例的字体
	QVector<QColor>   m_componentLegendColorVec;//饼图图例的字体的颜色

	QString m_titleName;//饼图标题名称
	QFont   m_titleFont;//饼图标题字体
	QColor  m_titleColor;//饼图标题字体颜色
};

#endif // HNPIECHART_H

2、实现文件如下:

#include "hnPieChart.h"
#include <QPainter>
#include <QFont>
#include <math.h>

hnPieChart::hnPieChart(QWidget *parent)
	: QWidget(parent)
{
	m_NumOfComponent = 0;
	ui.setupUi(this);
}

hnPieChart::~hnPieChart()
{

}

void hnPieChart::ClearPieChart()
{
	m_NumOfComponent = 0;
	m_componentNameVec.clear();
	m_componentNumberVec.clear();
	m_componentColorVec.clear();
	m_componentPercentageVec.clear();
	m_componentLegendFontVec.clear();
	m_componentLegendColorVec.clear();
}

void hnPieChart::SetChartTitle(const QString& titleName, QFont titleFont, QColor titleColor)
{
	m_titleName = titleName;
	m_titleFont = titleFont;
	m_titleColor= titleColor;
}

void hnPieChart::AddComponentToChart(const QString& name, int Num, QColor color, QFont lengendFont, QColor legendColor)
{
	m_componentNameVec.push_back(name);
	m_componentNumberVec.push_back(Num);
	m_componentColorVec.push_back(color);
	m_componentLegendFontVec.push_back(lengendFont);
	m_componentLegendColorVec.push_back(legendColor);
	m_NumOfComponent++;
}

void hnPieChart::DrawPieChart()
{
	QPainter painter(this);
	painter.setRenderHint(QPainter::Antialiasing, true);//抗锯齿

	QRect recTitle = ui.widget_title->geometry();
	painter.setFont(m_titleFont);
	painter.setPen(m_titleColor);
	painter.drawText(recTitle, Qt::AlignCenter, m_titleName);//设置饼图标题

	QRect recChart = ui.widget_chart->geometry();
	int minSide = 0;
	int bPx=0, bPy=0;
	if (recChart.width() > recChart.height())
	{
		minSide = recChart.height();
		bPx = recChart.x() + (recChart.width() - recChart.height()) / 2 + minSide / 10 / 2;
		bPy = recChart.y() + minSide / 10 / 2;
	}
	else
	{
		minSide = recChart.width();
		bPx = recChart.x() + minSide / 10 / 2;
		bPy = recChart.y() + (recChart.height() - recChart.width()) / 2 + minSide / 10 / 2;
	}
	int PieDiameter = minSide * 9 / 10;
	recChart = QRect(bPx, bPy, PieDiameter, PieDiameter);
	QPoint PieCenter(bPx+PieDiameter/2,bPy+PieDiameter/2);

	QBrush brush(Qt::SolidPattern);//设置画刷模式
	int startAngle = 0;
	int spanAngle = 0;
	if (m_NumOfComponent==1)//饼图只有一个组成部分
	{
		painter.setPen(Qt::NoPen);
		brush.setColor(m_componentColorVec[0]);
		painter.setBrush(brush);
		painter.drawPie(recChart, 0, 360*16);

		painter.setFont(m_componentLegendFontVec[0]);
		painter.setPen(m_componentLegendColorVec[0]);
		int per = 100;
		QString str = m_componentNameVec[0] + QString("(%1").arg(per) + "%)";
		painter.drawText(recChart, Qt::AlignCenter, str);
	} 
	else
	{
		for (int i = 0; i < m_NumOfComponent; i++)
		{
			spanAngle = 360 * m_componentPercentageVec[i] * 16;
			painter.setPen(Qt::NoPen);
			brush.setColor(m_componentColorVec[i]);
			painter.setBrush(brush);
			painter.drawPie(recChart, startAngle, spanAngle);

			int middleAngle = startAngle + spanAngle / 2;
			int middlePtx = PieCenter.rx() + PieDiameter / 2 * cos(middleAngle / 16.0 / 180 * 3.1416);
			int middlePty = PieCenter.ry() - PieDiameter / 2 * sin(middleAngle / 16.0 / 180 * 3.1416);

			int size = minSide / 10;
			QRect recLegend;
			painter.setPen(Qt::black);
			if (middleAngle<90*16&&middleAngle>=0*16)//第一象限
			{
				painter.drawLine(middlePtx,middlePty,middlePtx + size/2,middlePty);
				recLegend = QRect(middlePtx + size/2, middlePty - size/2, 2 * size, size);
			}
			if(middleAngle < 180*16&&middleAngle>=90*16)//第二象限
			{
				painter.drawLine(middlePtx, middlePty, middlePtx - size/2, middlePty);
				recLegend = QRect(middlePtx - size/2 - 2 * size, middlePty - size/2, 2 * size, size);
			}
			if (middleAngle<270*16&&middleAngle>=180*16)//第三象限
			{
				painter.drawLine(middlePtx, middlePty, middlePtx - size/2, middlePty);
				recLegend = QRect(middlePtx - size/2- 2 * size, middlePty - size/2, 2 * size, size);
			}
			if (middleAngle < 360*16&&middleAngle>=270*16)//第四象限
			{
				painter.drawLine(middlePtx, middlePty, middlePtx + size/2, middlePty);
				recLegend = QRect(middlePtx + size/2, middlePty - size/2, 2 * size, size);
			}

			painter.setFont(m_componentLegendFontVec[i]);
			painter.setPen(m_componentLegendColorVec[i]);
			float per = m_componentPercentageVec[i] * 100;
			QString str = m_componentNameVec[i] + QString("(%1").arg(per,0,'f', 2) + "%)";
			painter.drawText(recLegend, Qt::AlignCenter, str);

			startAngle += 360 * m_componentPercentageVec[i] * 16;
		}
	}
}

void hnPieChart::paintEvent(QPaintEvent *event)
{
	DrawPieChart();

	QWidget::paintEvent(event);
}

void hnPieChart::CalculatePercentage()
{
	m_componentPercentageVec.resize(m_NumOfComponent);
	int sum = 0;
	for (int i = 0; i < m_NumOfComponent; i++)
	{
		sum += m_componentNumberVec[i];
	}
	for (int i = 0; i < m_NumOfComponent; i++)
	{
		double per = (double)m_componentNumberVec[i] / sum;
		m_componentPercentageVec[i]=per;
	}
}

3、ui文件如下:

 4、调用如下:

#ifndef TEST_H
#define TEST_H

#include <QtWidgets/QMainWindow>
#include "ui_test.h"
#include "hnPieChart.h"

class test : public QMainWindow
{
	Q_OBJECT

public:
	test(QWidget *parent = 0);
	~test();

private:
	Ui::testClass ui;
	hnPieChart m_PieChart;//声明对象
};

#endif // TEST_H
#include "test.h"

test::test(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);

	//调用方式
	m_PieChart.ClearPieChart();
	m_PieChart.SetChartTitle(QString::fromLocal8Bit("超限状态图"), QFont(QString::fromLocal8Bit("微软雅黑"),12),Qt::black);
	m_PieChart.AddComponentToChart(QString::fromLocal8Bit("正常"), 5352, Qt::cyan, QFont(QString::fromLocal8Bit("微软雅黑"), 10),Qt::black);
	m_PieChart.AddComponentToChart(QString::fromLocal8Bit("拉出"), 20242, Qt::red, QFont(QString::fromLocal8Bit("微软雅黑"), 10),Qt::black);
	m_PieChart.AddComponentToChart(QString::fromLocal8Bit("导高"), 5000, Qt::green, QFont(QString::fromLocal8Bit("微软雅黑"), 10), Qt::black);
	m_PieChart.AddComponentToChart(QString::fromLocal8Bit("角度"), 21245, Qt::blue, QFont(QString::fromLocal8Bit("微软雅黑"), 10), Qt::black);
	m_PieChart.AddComponentToChart(QString::fromLocal8Bit("磨耗"), 50000, Qt::magenta, QFont(QString::fromLocal8Bit("微软雅黑"), 10), Qt::black);
    m_PieChart.CalculatePercentage();

	ui.verticalLayout->addWidget(&m_PieChart);
}

test::~test()
{

}

5、运行效果如下:

您可以使用Qt框架中的QPainter来自定义绘制刀切样式的饼图。下面是一个简单的示例代码,展示了如何使用QPainter绘制刀切样式的饼图: ```cpp #include <QPainter> #include <QPaintEvent> #include <QWidget> class PieChartWidget : public QWidget { public: PieChartWidget(QWidget *parent = nullptr) : QWidget(parent) {} protected: void paintEvent(QPaintEvent *event) override { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); QRectF pieRect(10, 10, width() - 20, height() - 20); int startAngle = 16; int spanAngle = 45 * 16; // 绘制刀切样式的饼图扇形 painter.setBrush(QColor(255, 0, 0)); painter.drawPie(pieRect, startAngle, spanAngle); painter.setBrush(QColor(0, 255, 0)); painter.drawPie(pieRect, startAngle + spanAngle, spanAngle); painter.setBrush(QColor(0, 0, 255)); painter.drawPie(pieRect, startAngle + spanAngle * 2, spanAngle); // 绘制刀切样式的切线 painter.setPen(Qt::black); painter.drawLine(pieRect.center(), pieRect.topRight()); painter.drawLine(pieRect.center(), pieRect.bottomRight()); painter.drawLine(pieRect.center(), pieRect.topLeft()); painter.drawLine(pieRect.center(), pieRect.bottomLeft()); // 绘制中间的圆形 painter.setBrush(Qt::white); painter.drawEllipse(pieRect.center(), pieRect.width() / 2.5, pieRect.height() / 2.5); } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); PieChartWidget widget; widget.show(); return app.exec(); } ``` 上述代码定义了一个自定义的QWidget派生PieChartWidget,重写了其paintEvent函数来进行绘图。在paintEvent函数中,使用QPainter的drawPie函数绘制了三个扇形,形成刀切样式的饼图。然后使用drawLine函数绘制了刀切样式的切线,最后使用drawEllipse函数绘制了中间的圆形。 您可以根据需要修改颜色、角度、大小等参数,以满足您的实际需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值