Qt加载动画
在做耗时任务时我们总是需要一个加载动画,我们平时都是用gif来做,但是需要找人设计,所以专门自定义一个加载动画
// 简单使用
// LoadingAnimation* loader = new LoadingAnimation(this);
// loader->show();
// 详细使用
LoadingAnimation* loader = new LoadingAnimation(this);
loader->setRadius(80);
loader->setCircleColor(QColor(52, 152, 219));
loader->setCircleWidth(8);
loader->setArcSpan(80);
loader->setAnimationDuration(1000);
loader->startAnimation();
loader->setBackgroundColor(Qt::white);
loader->show();
.h
// LoadingAnimation.h
#ifndef LOADINGANIMATION_H
#define LOADINGANIMATION_H
#include <QPainter>
#include <QPointer>
#include <QPropertyAnimation>
#include <QWidget>
class LoadingAnimation : public QWidget {
Q_OBJECT
Q_PROPERTY(int rotationAngle READ rotationAngle WRITE setRotationAngle)
public:
explicit LoadingAnimation(QWidget* parent = nullptr);
~LoadingAnimation();
void setCircleColor(const QColor& color);
void setCircleWidth(int width);
void setRadius(int radius);
void setArcSpan(int degrees);
void setAnimationDuration(int ms);
// 窗口背景色相关接口(整个控件的背景)
void setBackgroundColor(const QColor& color);
QColor backgroundColor() const { return m_backgroundColor; }
void setBackgroundTransparent(bool transparent);
bool isBackgroundTransparent() const { return m_backgroundTransparent; }
void startAnimation();
void stopAnimation();
void pauseAnimation();
void resumeAnimation();
void setRotationAngle(int angle);
int rotationAngle() const { return m_rotationAngle; }
protected:
void paintEvent(QPaintEvent* event) override;
private:
void updateSize();
void initAnimation();
void cleanupAnimation();
void updateWidgetAttributes();
private:
int m_rotationAngle;
QColor m_circleColor;
int m_circleWidth;
int m_radius;
int m_arcSpan;
// 窗口背景色相关
QColor m_backgroundColor; // 窗口背景色
bool m_backgroundTransparent; // 是否透明背景
// 使用 QPointer 自动检测对象是否被删除
QPointer<QPropertyAnimation> m_rotationAnimation;
bool m_animationPaused;
};
#endif
.cpp
// LoadingAnimation.cpp
#include "LoadingAnimation.h"
LoadingAnimation::LoadingAnimation(QWidget* parent)
: QWidget(parent)
, m_rotationAngle(0)
, m_circleColor(52, 152, 219) // 蓝色
, m_circleWidth(6)
, m_radius(40)
, m_arcSpan(120)
, m_backgroundColor(Qt::transparent) // 默认透明背景
, m_backgroundTransparent(true) // 默认透明
, m_rotationAnimation(nullptr)
, m_animationPaused(false)
{
updateWidgetAttributes();
updateSize();
initAnimation();
}
LoadingAnimation::~LoadingAnimation()
{
cleanupAnimation();
}
void LoadingAnimation::updateWidgetAttributes()
{
if (m_backgroundTransparent) {
// 透明背景模式
setAttribute(Qt::WA_TranslucentBackground);
setAutoFillBackground(false);
} else {
// 不透明背景模式
setAttribute(Qt::WA_TranslucentBackground, false);
setAutoFillBackground(true);
}
}
void LoadingAnimation::initAnimation()
{
// 先清理旧的动画对象
cleanupAnimation();
// 创建新的动画对象,this作为父对象确保自动清理
m_rotationAnimation = new QPropertyAnimation(this, "rotationAngle");
m_rotationAnimation->setDuration(1000);
m_rotationAnimation->setStartValue(0);
m_rotationAnimation->setEndValue(360);
m_rotationAnimation->setLoopCount(-1);
m_rotationAnimation->setEasingCurve(QEasingCurve::Linear);
m_rotationAnimation->start();
}
void LoadingAnimation::cleanupAnimation()
{
if (!m_rotationAnimation.isNull()) {
m_rotationAnimation->stop();
m_rotationAnimation->deleteLater();
m_rotationAnimation = nullptr;
}
}
void LoadingAnimation::updateSize()
{
int size = m_radius * 2 + m_circleWidth * 2;
setFixedSize(size, size);
}
void LoadingAnimation::setRotationAngle(int angle)
{
m_rotationAngle = angle % 360;
update();
}
void LoadingAnimation::setCircleColor(const QColor& color)
{
m_circleColor = color;
update();
}
void LoadingAnimation::setCircleWidth(int width)
{
if (width <= 0)
return;
m_circleWidth = width;
updateSize();
update();
}
void LoadingAnimation::setRadius(int radius)
{
if (radius <= 0)
return;
m_radius = radius;
updateSize();
update();
}
void LoadingAnimation::setArcSpan(int degrees)
{
m_arcSpan = qBound(10, degrees, 360);
update();
}
void LoadingAnimation::setAnimationDuration(int ms)
{
if (ms <= 0)
return;
if (m_rotationAnimation.isNull()) {
initAnimation();
}
m_rotationAnimation->setDuration(ms);
}
// 窗口背景色相关接口实现
void LoadingAnimation::setBackgroundColor(const QColor& color)
{
m_backgroundColor = color;
m_backgroundTransparent = (color.alpha() == 0);
updateWidgetAttributes();
update();
}
void LoadingAnimation::setBackgroundTransparent(bool transparent)
{
m_backgroundTransparent = transparent;
if (transparent) {
m_backgroundColor = Qt::transparent;
}
updateWidgetAttributes();
update();
}
void LoadingAnimation::startAnimation()
{
if (m_rotationAnimation.isNull()) {
initAnimation();
}
if (m_rotationAnimation && m_rotationAnimation->state() != QPropertyAnimation::Running) {
m_rotationAnimation->start();
m_animationPaused = false;
}
}
void LoadingAnimation::stopAnimation()
{
if (!m_rotationAnimation.isNull()) {
m_rotationAnimation->stop();
m_animationPaused = false;
}
}
void LoadingAnimation::pauseAnimation()
{
if (!m_rotationAnimation.isNull() && m_rotationAnimation->state() == QPropertyAnimation::Running) {
m_rotationAnimation->pause();
m_animationPaused = true;
}
}
void LoadingAnimation::resumeAnimation()
{
if (!m_rotationAnimation.isNull() && m_animationPaused) {
m_rotationAnimation->resume();
m_animationPaused = false;
}
}
void LoadingAnimation::paintEvent(QPaintEvent* event)
{
Q_UNUSED(event);
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
// 绘制窗口背景色(如果不透明)
if (!m_backgroundTransparent && m_backgroundColor.alpha() > 0) {
painter.fillRect(rect(), m_backgroundColor);
}
QRect rect = this->rect();
int centerX = rect.center().x();
int centerY = rect.center().y();
QRectF circleRect(centerX - m_radius, centerY - m_radius,
m_radius * 2, m_radius * 2);
// 只绘制旋转的圆弧(没有背景圆环)
QPen arcPen(m_circleColor);
arcPen.setWidth(m_circleWidth);
arcPen.setCapStyle(Qt::RoundCap);
painter.setPen(arcPen);
int spanAngle = m_arcSpan * 16;
int startAngle = (m_rotationAngle * 16) % (360 * 16);
painter.drawArc(circleRect, startAngle, spanAngle);
}


浙公网安备 33010602011771号