目标
- 基于Qwidget实现圆弧倒计时
- 可自定义圆弧内部显示的文字
- 可设定当前圆弧的进度
效果图

完整控件代码
CircleCountDownBar.h
#pragma once
#include <QWidget>
class QPaiter;
class QPaintEvent;
class CircleCountDownBar : public QWidget
{
Q_OBJECT
public:
CircleCountDownBar(QWidget* parent = nullptr);
~CircleCountDownBar();
///
/// @brief: 设置最大值与最小值
/// @param: const qreal minValue - 最小值
/// @param: const qreal maxValue - 最大值
/// @ret: void
///
///
void setRange(const qreal minValue, const qreal maxValue);
/// 设置当前值
void setCurValue(qreal cur_value);
/// 设置要绘制的文字
void setText(const QString& cur_text);
/// 绘制文字颜色
void setTextColor(const QColor& text_color);
private:
void paintEvent(QPaintEvent* event);
//void draw
private:
/// 大圆背景色
QColor m_bigCircleColor = QColor(230, 230, 230);
/// 扇形有效的颜色
QColor m_curPieValidColor = QColor("#2AEBA2");
/// 圆环无效的颜色
QColor m_pieInvalidColor = QColor(200, 200, 200);
/// 中间填充小圆形的颜色
QColor m_smallCircleColor = QColor(64, 64, 66);
/// 当前显示文本
QString m_curText{};
/// 当前文本显示颜色
QColor m_curTextColor = QColor(230, 230, 230);
/// 角度的最大值
qreal m_maxValue = 100;
/// 角度的最小值
qreal m_minValue = 0;
/// 起始角度, 0度 位于 X正半轴。倒数为正
qreal m_startAngle = 90;
/// 当前值
qreal m_curValue = 270;
};
CircleCountDownBar.cpp
#include "CircleCountDownBar.h"
#include <QPainter>
CircleCountDownBar::CircleCountDownBar(QWidget *parent)
: QWidget(parent)
{
setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground);
}
CircleCountDownBar::~CircleCountDownBar()
{
}
///
/// @brief: CircleCountDownBar::setRange
///
void CircleCountDownBar::setRange(const qreal minValue, const qreal maxValue)
{
m_maxValue = (0 >= maxValue ? 1 : maxValue);
m_minValue = (0 >= minValue ? 0 : minValue);
}
///
/// @brief: 设置当前值
///
void CircleCountDownBar::setCurValue(qreal cur_value)
{
if (cur_value <= m_minValue)
{
cur_value = m_minValue;
}
else if (cur_value >= m_maxValue)
{
cur_value = m_maxValue;
}
else
{
}
if (true == qFuzzyCompare(0.0, m_maxValue))
{
m_maxValue = 1.0;
}
m_curValue = ((m_maxValue - cur_value) * 360.0 / (m_maxValue));
update();
}
///
/// @brief: 设置要绘制的文字
///
void CircleCountDownBar::setText(const QString& cur_text)
{
m_curText = cur_text;
update();
}
///
/// @brief: CircleCountDownBar::setTextColor
///
void CircleCountDownBar::setTextColor(const QColor& text_color)
{
m_curTextColor = text_color;
update();
}
///
/// @brief:
///
void CircleCountDownBar::paintEvent(QPaintEvent* event)
{
int width = this->width();
int height = this->height();
int side = qMin(width, height);
//绘制准备工作,启用反锯齿,平移坐标轴中心,等比例缩放
QPainter painter(this);
QRect new_rect = this->rect();
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing, true);
painter.translate(width / 2, height / 2);
painter.scale(side / 200.0, side / 200.0);
/// 背景色
painter.fillRect(new_rect, QColor(0,0,0,0));
{
int radius = 100;
painter.save();
/// 绘制灰色背景
painter.setPen(Qt::NoPen);
painter.setBrush(m_curPieValidColor);
painter.drawEllipse(-radius, -radius, radius * 2, radius * 2);
painter.restore();
}
/// 小圆形
{
int radius = 80;
painter.save();
painter.setPen(Qt::NoPen);
painter.setBrush(m_bigCircleColor);
painter.drawEllipse(-radius, -radius, radius * 2, radius * 2);
painter.restore();
}
/// 绘制扇形颜色
{
int radius = 100;
painter.save();
painter.setPen(Qt::NoPen);
painter.setBrush(m_pieInvalidColor);
int startAngle = m_startAngle * 16;
int spanAngle = m_curValue * 16;
painter.drawPie(-radius, -radius, radius*2, radius*2, startAngle, spanAngle);
painter.restore();
}
/// 绘制遮盖白色圆形
{
int radius = 80;
painter.save();
painter.setPen(Qt::NoPen);
painter.setBrush(m_smallCircleColor);
painter.drawEllipse(-radius, -radius, radius * 2, radius * 2);
painter.restore();
}
/// 绘制文字
{
int radius = 80;
painter.save();
painter.setPen(m_curTextColor);
painter.setBrush(Qt::NoBrush);
QFont font = painter.font();
font.setPixelSize(20);
painter.setFont(font);
QRectF textRect(-radius, -radius, radius * 2, radius * 2);
painter.drawText(textRect, Qt::AlignCenter, m_curText);
painter.restore();
}
}