头文件
#ifndef QWHPIE_H
#define QWHPIE_H
#include
#include
#include
class QWHPie : public QWidget
{
Q_OBJECT
public:
enum LegendAlign
{
LegendAlign_Bottom, //图例在底部
LegendAlign_Right, //图例在右侧
};
struct PieData
{
QString name; //名称
double percent; //百分比
QColor color; //颜色
PieData(QString name, double percent, QColor color){
this->name = name;
this->percent = percent;
this->color = color;
}
};
explicit QWHPie(QWidget *parent = nullptr);
void setPieDatas(QList pieDatas, int columnCount);
void addPieData(PieData pieData, int index);
void removePieData(int index);
protected:
void paintEvent(QPaintEvent *event);
void drawTitle(QPainter *painter);
void drawName(QPainter *painter);
void drawPie(QPainter *painter);
void drawLegend(QPainter *painter);
private:
double degreeToRadius(double degree);
signals:
public slots:
private:
bool m_showTitle; //是否显示标题
QString m_title; //标题名称
int m_titleHeight; //标题高度
QColor m_tileColor; //标题颜色
bool m_showLegend; //是否显示图例
int m_legendHeight; //图例高度
int m_legendWidth; //图例宽度
int m_legendColumnCount; //图例列数
int m_legendCount; //图列数量
LegendAlign m_legendAlign; //图例位置
int m_margin; //图例边距
QColor m_legendNameColor; //图例名称颜色
bool m_showPieMargin; //饼图各模块连接是否有缝隙
QColor m_pieMarginColor; //饼图边缘颜色
float m_pieDataRadius; //饼图数据距中心点距离
QList m_PieDatas; //饼图数据集合
};
#endif // QWHPIE_H
核心代码
void QWHPie::paintEvent(QPaintEvent *event)
{
QPainter painter(this);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
//绘制标题
drawTitle(&painter);
//绘制饼图
drawPie(&painter);
//绘制饼图文字(百分比前面的具体内容)
//drawName(&painter);
//绘制图例
drawLegend(&painter);
}
void QWHPie::drawTitle(QPainter *painter)
{
painter->save();
QRect rect(0, 0, this->width(), m_titleHeight);
painter->drawText(rect, Qt::AlignCenter, m_title);
painter->restore();
}
void QWHPie::drawPie(QPainter *painter)
{
painter->save();
int width = this->width();
int height = this->height();
painter->setPen(Qt::white);
int legendRows = 0;
if (m_legendAlign == LegendAlign_Bottom)
{
legendRows = qCeil(m_legendCount * 1.0 / m_legendColumnCount);
QRect rect(0, m_titleHeight, width, height - m_titleHeight - legendRows * m_legendHeight);
painter->translate(rect.center());
int side = qMin(rect.width(), rect.height());
painter->scale(side / 100, side / 100);
}
else if (m_legendAlign == LegendAlign_Right)
{
QRect rect(0, m_titleHeight, width - m_legendColumnCount * m_legendWidth, height - m_titleHeight);
painter->translate(rect.center());
int side = qMin(rect.width(), rect.height());
painter->scale(side / 100, side / 100);
}
int radius = 49;
double startAngle = 0;
QRect rect = QRect(-radius, -radius, 2 * radius, 2 * radius);
for (int i = 0; i < m_legendCount; i++)
{
//绘制扇形区域
double angle = m_PieDatas.at(i).percent * 1.0 / 100 * 360;
painter->setPen(Qt::white);
painter->setBrush(m_PieDatas.at(i).color);
painter->drawPie(rect, startAngle * 16, angle * 16);
//绘制扇区文本
int textAngle = (startAngle + (startAngle + angle)) / 2;
int x = radius * m_pieDataRadius * qCos(degreeToRadius(textAngle));
int y = radius * m_pieDataRadius * qSin(degreeToRadius(textAngle));
QFont font;
font.setPixelSize(5);
painter->setFont(font);
QRectF textRect = QRectF(x - radius, -y - radius, 2 * radius, 2 * radius);
QString text = QString("%1%").arg(m_PieDatas.at(i).percent);
painter->setPen(Qt::black);
painter->drawText(textRect, Qt::AlignCenter, text);
startAngle += angle;
}
painter->restore();
}
void QWHPie::drawLegend(QPainter *painter)
{
painter->save();
int width = this->width();
int height = this->height();
int side = qMin(width, height);
if (m_legendAlign == LegendAlign_Bottom)
{
int legendRows = qCeil(m_legendCount * 1.0 / m_legendColumnCount);
int legendWidth = width / m_legendColumnCount;
painter->translate(0, height - legendRows * m_legendHeight);
int rowIndex = 0;
int columnIndex = 0;
for (int i = 0; i < m_legendCount; i++)
{
int x = columnIndex * legendWidth + m_margin;
QRect rectLegend(x, rowIndex * m_legendHeight, 0.8 * m_legendHeight, 0.8 * m_legendHeight);
painter->setPen(m_PieDatas.at(i).color);
painter->setBrush(m_PieDatas.at(i).color);
painter->drawRoundedRect(rectLegend, 0.1 * m_legendHeight, 0.1 * m_legendHeight);
painter->setPen(m_legendNameColor);
painter->setBrush(m_legendNameColor);
x = columnIndex * legendWidth + m_margin + m_legendHeight;
QRect rectText(x, rowIndex * m_legendHeight, legendWidth - m_margin - m_legendHeight, 0.8 * m_legendHeight);
QString text = QString("%1: %2%").arg(m_PieDatas.at(i).name).arg(m_PieDatas.at(i).percent);
painter->drawText(rectText, Qt::AlignVCenter | Qt::AlignLeft, text);
columnIndex++;
if (columnIndex % m_legendColumnCount == 0)
{
columnIndex = 0;
rowIndex++;
}
}
}
else if (m_legendAlign == LegendAlign_Right)
{
int legendRows = qCeil(m_legendCount * 1.0 / m_legendColumnCount);
int legendWidth = m_legendWidth;
int legendHeight = (height - m_titleHeight) / legendRows;
painter->translate(0, m_titleHeight);
int rowIndex = 0;
int columnIndex = 0;
for (int i = 0; i < m_legendCount; i++)
{
int x = (width - m_legendColumnCount * m_legendWidth) + columnIndex * legendWidth + m_margin;
QRect rectLegend(x, rowIndex * legendHeight, 0.8 * m_legendHeight, 0.8 * m_legendHeight);
painter->setPen(m_PieDatas.at(i).color);
painter->setBrush(m_PieDatas.at(i).color);
painter->drawRoundedRect(rectLegend, 0.1 * m_legendHeight, 0.1 * m_legendHeight);
x = (width - m_legendColumnCount * m_legendWidth) + columnIndex * legendWidth + m_margin + m_legendHeight;
QRect rectText(x, rowIndex * legendHeight, legendWidth, 0.8 * m_legendHeight);
QString text = QString("%1: %2%").arg(m_PieDatas.at(i).name).arg(m_PieDatas.at(i).percent);
painter->drawText(rectText, Qt::AlignVCenter | Qt::AlignLeft, text);
columnIndex++;
if (columnIndex % m_legendColumnCount == 0)
{
columnIndex = 0;
rowIndex++;
}
}
}
painter->restore();
}