目录
1.简介

在日常开发的的 Qt 应用中,执行耗时任务时,如何优雅地告知用户"程序正在努力工作中",是提升用户体验的一个关键环节。
常见的实现方法大概有这么几种:比如用 QMovie 加载一张 GIF 动图,或者自绘一个动画控件,又或者是使用 QProgressIndicator 等类似的控件。它们各有各的问题:用 GIF 会带来额外的资源加载负担,而且尺寸一拉伸就容易糊;自己造轮子虽然自由度高,但需要做的代码量实在不菲,其中涉及到的数学计算更是相当耗时。
WaitingSpinnerWidget正是为了解决这些痛点而诞生的轻量级"轮子"。它是一个高度可配置的自定义 Qt 小部件,专门用于在 Qt 应用程序中显示等待或加载旋转图标。通过这个控件,开发者能够轻松地将丝滑的等待动画集成到各类应用中,并且完全掌握其外观和行为的定制权。
2.主要实现版本
1.C++ Qt 版本(snowwlex/QtWaitingSpinner)
- 官方 GitHub: https://github.com/snowwlex/QtWaitingSpinner
- 基于 Qt Widgets,兼容 Qt 5.x 和 Qt 6.x
- 纯 C++ 实现,无外部依赖
- 提供静态库和动态库两种编译方式
2.Python PyQt/PySide 版本
| 项目名称 | 特点 | 安装命令 |
|---|---|---|
| PyQtWaitingSpinner | 兼容 PyQt5/6 和 PySide2/6,文档完善 | pip install pyqtwaitingspinner |
| pyqtspinner | 轻量级,基于原始 C++ 版本的 Python 移植 | pip install pyqtspinner |
| PrettyQt | 集成在 PrettyQt 自定义控件库中 | pip install prettyqt |
3.安装与集成
1.C++ Qt 安装
cpp
# 克隆仓库
git clone https://github.com/snowwlex/QtWaitingSpinner.git
# 在Qt Creator中打开项目并编译
# 或使用qmake手动编译
cd QtWaitingSpinner
mkdir build && cd build
qmake ..
make -j4
也可以从百度网盘下载:
通过网盘分享的文件:QtWaitingSpinner.zip
链接: https://pan.baidu.com/s/16hcvbthBhL1aH2rqBOcZKQ?pwd=1234 提取码: 1234
2.Python 安装
cpp
# 安装PyQt版本
pip install pyqtwaitingspinner
# 或安装pyqtspinner
pip install pyqtspinner
3.集成到 Qt 项目
将 QtWaitingSpinner 的源文件(通常为 waitingspinnerwidget.h 和 waitingspinnerwidget.cpp)添加到你的项目中。在项目文件(.pro)中,可以这样引入:
cpp
include(path/to/QtWaitingSpinner/qtwaitingspinner.pri)
4.直接使用源码
把waitingspinnerwidget.h和waitingspinnerwidget.cpp拷贝到你的源码目录,加入到你的工程中,直接使用即可。
4.核心特性与配置选项
该组件提供了丰富的自定义参数,可灵活调整动画外观和行为:
| 配置项 | 说明 |
|---|---|
| 颜色 (Colour) | 线条的主色调,支持自定义 QColor |
| 线条圆润度 (Roundness) | 线条端点的圆角程度,0-100% |
| 旋转速度 (Speed) | 每秒旋转次数,默认 1.5 转 |
| 线条数量 (Number of lines) | 组成动画的线条总数,默认 12 条 |
| 线条长度 (Line length) | 每条线的像素长度,默认 10px |
| 线条宽度 (Line width) | 线条粗细,默认 2px |
| 内圆半径 (Inner radius) | 中心 "空白区域" 的半径,默认 10px |
| 轨迹淡入淡出 (Fade percentage) | 线条尾部的透明度衰减比例,默认 80% |
| 最小不透明度 (Minimum opacity) | 线条尾部的最低透明度,默认 30% |
| 旋转方向 (Direction) | 顺时针或逆时针旋转 |
| 中心文字 (Text) | 部分扩展版本支持在中间显示加载提示文字 |
5.完整示例
cpp
#include <QApplication>
#include <QWidget>
#include <QVBoxLayout>
#include "waitingspinnerwidget.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
QWidget w;
w.setWindowTitle("WaitingSpinner Example");
w.resize(300, 200);
QVBoxLayout* layout = new QVBoxLayout(&w);
// 创建并配置等待动画
WaitingSpinnerWidget* spinner = new WaitingSpinnerWidget(&w);
spinner->setColor(Qt::blue);
spinner->setLineLength(15);
spinner->setLineWidth(3);
spinner->setInnerRadius(15);
spinner->setRevolutionsPerSecond(2); // 每秒2转
layout->addWidget(spinner, 0, Qt::AlignCenter);
// 开始动画
spinner->start();
w.show();
return a.exec();
}
6.高级用法
1.模态等待对话框
cpp
// 创建覆盖整个父窗口的模态等待动画
WaitingSpinnerWidget* spinner = new WaitingSpinnerWidget(parentWidget, true, true);
spinner->start();
// 执行耗时操作...
spinner->stop();
spinner->deleteLater();
2.与异步操作结合
cpp
import threading
import time
from PyQt6.QtCore import QThread, pyqtSignal
class WorkerThread(QThread):
finished = pyqtSignal()
def run(self):
# 模拟耗时操作
time.sleep(3)
self.finished.emit()
# 在主线程中
spinner.start()
thread = WorkerThread()
thread.finished.connect(lambda: spinner.stop())
thread.start()
3.自定义样式
cpp
// 完全自定义外观
spinner->setColor(QColor(255, 87, 51)); // 橙色
spinner->setRoundness(70.0); // 高圆润度
spinner->setTrailFadePercentage(70.0);
spinner->setMinimumTrailOpacity(20.0);
spinner->setNumberOfLines(20);
spinner->setLineLength(20);
spinner->setLineWidth(4);
spinner->setInnerRadius(20);
spinner->setRevolutionsPerSecond(1.0);
7.常见问题与解决方案
| 问题 | 解决方案 |
|---|---|
| 动画卡顿 | 确保在主线程中启动 / 停止动画,耗时操作放在子线程中执行 |
| 样式不生效 | 检查是否在 start () 之前设置属性,部分属性需要重新 start () 才能生效 |
| 背景不透明 | 设置第二个构造函数参数为 false,或调用 setBackgroundColor () 设置透明背景 |
| 与布局冲突 | 将 spinner 添加到布局中,或设置固定大小后手动定位 |