菊花圆圈转动动画

CustomProgressIndicator.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#ifndef CUSTOMPROGRESSINDICATOR_H
#define CUSTOMPROGRESSINDICATOR_H

#include <QWidget>
#include <QColor>
/*
* 菊花转 进度类,基于代码无需图片资源
* 作者:陈鲁勇
* 邮箱:727057301@qq.com
* 创建时间:2017年2月10日16:26:48
* QT版本:5.0.2
* CSDN:http://blog.csdn.net/csnd_ayo
* **************************************
* 说明:
* 使用前请确保在QT.pro中加入 C++11 的支持
*
* 示例代码:
pIndicator = new CustomProgressIndicator(this);
pIndicator->setColor(Qt::red);
pIndicator->startAnimation();
*/

class CustomProgressIndicator : public QWidget
{
Q_OBJECT
Q_PROPERTY(int delay READ animationDelay WRITE setAnimationDelay)
Q_PROPERTY(bool displayedWhenStopped READ isDisplayedWhenStopped WRITE setDisplayedWhenStopped)
Q_PROPERTY(QColor color READ color WRITE setColor)
public:
CustomProgressIndicator(QWidget* parent = 0);

int animationDelay() const { return delay_; }

/* 动画是否正在进行中 */
bool isAnimated () const;

/* 动画完毕后,是否隐藏菊花转 */
bool isDisplayedWhenStopped() const;

/* 当前菊花转的颜色 */
const QColor & color() const { return color_; }

/* 虚函数:当前大小 */
virtual QSize sizeHint() const;

void setBackground(const QString& _icon) {
currentPix_ = QPixmap(_icon);
}
signals:
void Finished(void);
public slots:

/* 开始动画 */
void startAnimation();

/* 停止动画 */
void stopAnimation();

/* 设置菊花转的转速 */
void setAnimationDelay(int delay);

/* 动画完毕后,是否隐藏菊花转 */
void setDisplayedWhenStopped(bool state);

/* 设置菊花转颜色 */
void setColor(const QColor & color);

/*
* 进度
* 参数 _progress:当前进度 0 < _progress < 100
*/
void onProgress(short _progress) { progress_ = _progress; }
protected:
/* 系统基类函数 */
virtual void timerEvent(QTimerEvent * event);
virtual void paintEvent(QPaintEvent * event);
private:
/* 角度 */
unsigned int angle_;
/* 定时器ID */
int timerId_;
/* 转速 */
int delay_;
/* 是否隐藏 */
bool displayedWhenStopped_;
/* 菊花转颜色 */
QColor color_;
/* 进度 */
short progress_;
/* 背景图 */
QPixmap currentPix_;
};


#endif // CUSTOMPROGRESSINDICATOR_H

CustomProgressIndicator.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include "customprogressindicator.h"
#include <QPainter>

CustomProgressIndicator::CustomProgressIndicator(QWidget* parent)
: QWidget(parent),
angle_(0),
timerId_(-1),
delay_(20),
displayedWhenStopped_(false),
color_(Qt::green) {
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
setFocusPolicy(Qt::NoFocus);
}

bool CustomProgressIndicator::isAnimated () const {
return (timerId_ != -1);
}

void CustomProgressIndicator::setDisplayedWhenStopped(bool state) {
displayedWhenStopped_ = state;

update();
}

bool CustomProgressIndicator::isDisplayedWhenStopped() const {
return displayedWhenStopped_;
}

void CustomProgressIndicator::startAnimation() {
angle_ = 0;

if (timerId_ == -1) {
timerId_ = startTimer(delay_);
}
}

void CustomProgressIndicator::stopAnimation() {
if (timerId_ != -1) {
killTimer(timerId_);
}

timerId_ = -1;

update();
}

void CustomProgressIndicator::setAnimationDelay(int delay) {
if (timerId_ != -1){
killTimer(timerId_);
}

delay_ = delay;

if (timerId_ != -1){
timerId_ = startTimer(delay_);
}
}

void CustomProgressIndicator::setColor(const QColor & color) {
color_ = color;

update();
}

QSize CustomProgressIndicator::sizeHint() const {
return QSize(25,25);
}


void CustomProgressIndicator::timerEvent(QTimerEvent * /*event*/) {
angle_ = (angle_+30)%360;

update();
}

void CustomProgressIndicator::paintEvent(QPaintEvent * /*event*/) {
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);
if (!displayedWhenStopped_ && !isAnimated()) {
p.drawPixmap(rect(),currentPix_);
return;
}

int width = qMin(this->width(), this->height());


int outerRadius = (width-1) >> 1;
int innerRadius = ((width-1) >> 1)*0.38;

int capsuleHeight = outerRadius - innerRadius;
int capsuleWidth = (width > 32 ) ? capsuleHeight *.23 : capsuleHeight *.35;
int capsuleRadius = capsuleWidth >> 1;

/* 撰写进度 */
if (progress_ > 0 && progress_ < 100) {
p.setPen(color_);
p.drawText(rect(), Qt::AlignCenter, QString("%1%").arg(progress_));
}
else if (progress_ == 100) {
stopAnimation();
}

for (int i=0; i<12; ++i) {
QColor color = color_;
color.setAlphaF(1.0f - (i/12.0f));
p.setPen(Qt::NoPen);
p.setBrush(color);
p.save();
p.translate(rect().center());
p.rotate(angle_ - i*30.0f);
p.drawRoundedRect(((-capsuleWidth) >> 1), -(innerRadius+capsuleHeight), capsuleWidth, capsuleHeight, capsuleRadius, capsuleRadius);
p.restore();
}
}