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

完整控件代码
CircleCountDownBar.h
#pragma once#include <QWidget>
class QPaiter;
class QPaintEvent;class CircleCountDownBar : public QWidget
{Q_OBJECTpublic: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();}
}