前言
- 本文源码基于开源的代码改进而来, 具体出处无法溯源。
效果

功能
- 支持鼠标左键点击进图条设置值
- 支持显示当前数值
- 支持设置填充部分和未填充部分的颜色
- 开箱即用
源码
ProgressBar.h
#pragma once
#include <QWidget>
class ProgressBar : public QWidget
{
Q_OBJECT
public:
explicit ProgressBar(QWidget *parent = nullptr);
virtual ~ProgressBar();
void setMaxValue(int nValue);
int maxValue()const;
void setMinValue(int nValue);
int minValue()const;
void setRange(int nMin, int nMax);
int value()const;
/// 滑块没有填充的部分颜色,比如:"#FF00FF"
void setBKRectBrush(const QString& brush);
QString backRectBrush()const;
/// 设置填充矩形的渐变色
void setFillRectColor(const QLinearGradient& lg);
///
/// @brief: 设置圆角矩形的值, 默认20
/// @param: dbRadius
/// @return: void
///
void setRadius(double dbRadius);
///
/// @brief: 设置当前值显示的颜色,
/// @param: str 比如: #FF00FF
/// @return: void
///
void setValueTextColor(const QString& str);
///
/// @brief: 设置当前文字的大小
/// @param: size
/// @return: void
///
void setValueTextPointSize(int size);
protected:
virtual void paintEvent(QPaintEvent *event)override;
virtual void mouseMoveEvent(QMouseEvent *event)override;
virtual void mousePressEvent(QMouseEvent *event)override;
virtual void mouseReleaseEvent(QMouseEvent *event)override;
virtual bool eventFilter(QObject *o, QEvent *e)override;
private:
void drawBackRect(QPainter& painter);
void drawProcess(QPainter& painter);
void drawCurrentValueText(QPainter& painter);
private:
void updateValue(int nCurValue);
void initValue();
void initUISetting();
signals:
void sigValueChanged(qint32 nValue);
public slots:
void setValue(int nValue);
private:
struct stRange
{
int m_nMin{0};
int m_nMax{100};
}m_range;
int m_nCurValue{0};
double m_dbCurPercent{0.0};
double m_dbRadius{16};
QString m_bkRectBrush{};
bool m_bPressed{false};
/// 文字的颜色, 比如: "#FF00FF"
QString m_valueTextColor{"#FCFCFC"};
/// 文字的大小
int m_valueTextPointSize{ 12 };
/// 填充进度的渐变色
QLinearGradient m_fillRectLineGradient{};
};
ProgressBar.cpp
#include "ProgressBar.h"
#include <QPainter>
#include <QMouseEvent>
#include <QFontMetrics>
#include <QLinearGradient>
ProgressBar::ProgressBar(QWidget* parent)
: QWidget(parent)
{
initUISetting();
initValue();
setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground);
}
ProgressBar::~ProgressBar()
{
}
void ProgressBar::setMaxValue(int nValue)
{
if (nValue < m_range.m_nMin)
{
nValue = m_range.m_nMin;
}
m_range.m_nMax = nValue;
updateValue(0);
}
int ProgressBar::maxValue() const
{
return m_range.m_nMax;
}
void ProgressBar::setMinValue(int nValue)
{
if (nValue > m_range.m_nMax)
{
nValue = m_range.m_nMax;
}
m_range.m_nMin = nValue;
updateValue(0);
}
int ProgressBar::minValue() const
{
return m_range.m_nMin;
}
void ProgressBar::setRange(int nMin, int nMax)
{
if (nMax < nMin)
{
nMax = nMin;
}
m_range.m_nMin = nMin;
m_range.m_nMax = nMax;
updateValue(0);
}
void ProgressBar::setValue(int nValue)
{
updateValue(nValue);
}
int ProgressBar::value() const
{
return m_nCurValue;
}
void ProgressBar::setBKRectBrush(const QString& brush)
{
if (m_bkRectBrush == brush)
{
return;
}
m_bkRectBrush = brush;
update();
}
QString ProgressBar::backRectBrush() const
{
return m_bkRectBrush;
}
///
/// @brief: setFillRectColor
/// @param: lg
/// @return: void
///
void ProgressBar::setFillRectColor(const QLinearGradient& lg)
{
if (m_fillRectLineGradient == lg)
{
return;
}
m_fillRectLineGradient = lg;
update();
}
void ProgressBar::setRadius(double dbRadius)
{
if (qFuzzyCompare(m_dbRadius, dbRadius))
{
return;
}
m_dbRadius = dbRadius;
update();
}
///
/// @brief: 设置当前值显示的颜色
/// @param: str
/// @return: void
///
void ProgressBar::setValueTextColor(const QString& str)
{
m_valueTextColor = str;
update();
}
///
/// @brief: setValueTextPointSize
/// @param: size
/// @return: void
///
void ProgressBar::setValueTextPointSize(int size)
{
m_valueTextPointSize = size;
}
void ProgressBar::paintEvent(QPaintEvent* event)
{
QPainter painter(this);
painter.setPen(Qt::NoPen);
painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
painter.setBrush(Qt::NoBrush);
drawBackRect(painter);
drawProcess(painter);
drawCurrentValueText(painter);
}
void ProgressBar::mouseMoveEvent(QMouseEvent* event)
{
if (m_bPressed)
{
m_dbCurPercent = (event->pos().x() - m_dbRadius) * 1.0 / (width() - 2 * m_dbRadius);
m_dbCurPercent = std::min(1.0, m_dbCurPercent);
m_dbCurPercent = std::max(0.0, m_dbCurPercent);
m_nCurValue = (m_range.m_nMax - m_range.m_nMin) * m_dbCurPercent;
emit sigValueChanged(m_nCurValue);
update();
}
QWidget::mouseMoveEvent(event);
}
void ProgressBar::mousePressEvent(QMouseEvent* event)
{
m_bPressed = true;
m_dbCurPercent = (event->pos().x() - m_dbRadius) * 1.0 / (width() - 2 * m_dbRadius);
m_nCurValue = (m_range.m_nMax - m_range.m_nMin) * m_dbCurPercent;
emit sigValueChanged(m_nCurValue);
update();
}
void ProgressBar::mouseReleaseEvent(QMouseEvent* event)
{
m_bPressed = false;
QWidget::mouseReleaseEvent(event);
}
bool ProgressBar::eventFilter(QObject* o, QEvent* e)
{
return QWidget::eventFilter(o, e);
}
void ProgressBar::drawBackRect(QPainter& painter)
{
painter.save();
painter.setBrush(QColor(m_bkRectBrush));
painter.drawRoundedRect(QRect(0, 0, width() , this->height()), m_dbRadius, m_dbRadius);
painter.restore();
}
void ProgressBar::drawProcess(QPainter& painter)
{
painter.save();
QRect rectf(0, 0, width() * m_dbCurPercent, this->height());
QLinearGradient lineGradient = m_fillRectLineGradient;
lineGradient.setStart(QPoint(0, 0));
lineGradient.setFinalStop(QPoint(width(), 0));
painter.setBrush(lineGradient);
painter.drawRoundedRect(rectf, m_dbRadius, m_dbRadius);
painter.restore();
}
///
/// @brief: drawCurrentValueText
/// @param: painter
/// @return: void
///
void ProgressBar::drawCurrentValueText(QPainter& painter)
{
painter.save();
const QString valueText = QString::number(static_cast<int>(m_dbCurPercent * 100));
painter.setPen(QPen(QColor(m_valueTextColor), 2));
painter.setBrush(Qt::NoBrush);
{
QFont tmpFont = painter.font();
tmpFont.setPointSize(m_valueTextPointSize);
tmpFont.setBold(true);
painter.setFont(tmpFont);
}
QFontMetrics fm(painter.font());
int fontW = fm.width(valueText);
QSize textSize{ fontW, height()};
QRect valueRect{QPoint(width() - textSize.width() - 10, 0), textSize};
painter.drawText(valueRect, Qt::AlignVCenter | Qt::AlignRight, valueText);
painter.restore();
}
void ProgressBar::updateValue(int nCurValue)
{
if (m_nCurValue == nCurValue)
{
return;
}
m_nCurValue = nCurValue;
if (m_range.m_nMax == m_range.m_nMin)
m_dbCurPercent = 0;
else
m_dbCurPercent = m_nCurValue * 1.0 / (m_range.m_nMax - m_range.m_nMin);
update();
}
void ProgressBar::initValue()
{
m_range = { 0, 100 };
m_nCurValue = 0;
m_dbCurPercent = 0;
m_bkRectBrush = {"#5D6B99"};
m_bPressed = false;
m_fillRectLineGradient.setColorAt(0, QColor("#00b09b"));
m_fillRectLineGradient.setColorAt(1, QColor("#96c93d"));
}
void ProgressBar::initUISetting()
{
//setCursor(QCursor(Qt::PointingHandCursor));
setMouseTracking(true);
setFocusPolicy(Qt::StrongFocus);
}