一、效果展示
原理详解请参考:Qt定时器使用总结+动画实例
二、源码
#ifndef
#define
#include <QWidget>
#include <QColor>
#include <QDesktopWidget>
#include <QApplication>
class QProgressIndicator : 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:
QProgressIndicator(QWidget* parent = 0);
int animationDelay() const { return m_delay; }
bool isAnimated () const;
bool isDisplayedWhenStopped() const;
const QColor & color() const { return m_color; }
virtual QSize sizeHint() const;
int heightForWidth(int w) const;
public slots:
void startAnimation();
void stopAnimation();
void setAnimationDelay(int delay);
void setDisplayedWhenStopped(bool state);
void setColor(const QColor & color);
protected:
virtual void timerEvent(QTimerEvent * event);
virtual void paintEvent(QPaintEvent * event);
private:
int m_angle;
int m_timerId;
int m_delay;
bool m_displayedWhenStopped;
QColor m_color;
};
#endif// QPROGRESSINDICATOR_H
#include "qprogressindicator.h"
#include <QPainter>
QProgressIndicator::QProgressIndicator(QWidget* parent)
: QWidget(parent),
m_angle(0),
m_timerId(-1),
m_delay(40),
m_displayedWhenStopped(false),
m_color(Qt::black)
{
setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
setFocusPolicy(Qt::NoFocus);
setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint); //设置窗体无标题栏,隐藏任务栏,霸道显示在最顶层
setAttribute(Qt::WA_TranslucentBackground); //设置面板透明
showNormal();
this->setFixedSize(200,200); //固定大小
QDesktopWidget *pDesk = QApplication::desktop(); //居中显示
this->move((pDesk->width() - this->width()) / 2, (pDesk->height() - this->height()) / 2);
}
bool QProgressIndicator::isAnimated () const
{
return (m_timerId != -1);
}
void QProgressIndicator::setDisplayedWhenStopped(bool state)
{
m_displayedWhenStopped = state;
update();
}
bool QProgressIndicator::isDisplayedWhenStopped() const
{
return m_displayedWhenStopped;
}
void QProgressIndicator::startAnimation()
{
m_angle = 0;
if (m_timerId == -1)
m_timerId = startTimer(m_delay);
}
void QProgressIndicator::stopAnimation()
{
if (m_timerId != -1)
killTimer(m_timerId);
m_timerId = -1;
update();
}
void QProgressIndicator::setAnimationDelay(int delay)
{
if (m_timerId != -1)
killTimer(m_timerId);
m_delay = delay;
if (m_timerId != -1)
m_timerId = startTimer(m_delay);
}
void QProgressIndicator::setColor(const QColor & color)
{
m_color = color;
update();
}
QSize QProgressIndicator::sizeHint() const
{
return QSize(20,20);
}
int QProgressIndicator::heightForWidth(int w) const
{
return w;
}
void QProgressIndicator::timerEvent(QTimerEvent * /*event*/)
{
m_angle = (m_angle+30)%360;
update();
}
void QProgressIndicator::paintEvent(QPaintEvent * event)
{
Q_UNUSED(event)
if (!m_displayedWhenStopped && !isAnimated())
return;
int width = qMin(this->width(), this->height());
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing);
int outerRadius = (width-1)*0.5;
int innerRadius = (width-1)*0.5*0.38;
int capsuleHeight = outerRadius - innerRadius;
int capsuleWidth = (width > 32 ) ? capsuleHeight *.23 : capsuleHeight *.35;
int capsuleRadius = capsuleWidth/2;
for (int i=0; i<12; i++)
{
QColor color = m_color;
color.setAlphaF(1.0f - (i/12.0f));
p.setPen(Qt::NoPen);
p.setBrush(color);
p.save();
p.translate(rect().center());
p.rotate(m_angle - i*30.0f);
p.drawRoundedRect(-capsuleWidth*0.5, -(innerRadius+capsuleHeight), capsuleWidth, capsuleHeight, capsuleRadius, capsuleRadius);
p.restore();
}
}