//.h
//////////////////////////////////////////////////////////////////////////////
// Date of creation: 04.07.2013
// Creator: Alexander Egorov aka mofr
// Modifier : sp.Park 2018.10.30
// Authors: mofr
//////////////////////////////////////////////////////////////////////////////
#pragma once
#include <QWidget>
#include <QPropertyAnimation>
class ProgressCircle : public QWidget
{
private:
Q_OBJECT
Q_PROPERTY(int value READ value WRITE setValue NOTIFY valueChanged)
Q_PROPERTY(int maximum READ maximum WRITE setMaximum NOTIFY maximumChanged)
Q_PROPERTY(qreal innerRadius READ innerRadius WRITE setInnerRadius)
Q_PROPERTY(qreal outerRadius READ outerRadius WRITE setOuterRadius)
Q_PROPERTY(QColor color READ color WRITE setColor)
Q_PROPERTY(qreal infiniteAnimationValue READ infiniteAnimationValue WRITE setInfiniteAnimationValue)
Q_PROPERTY(int visibleValue READ visibleValue WRITE setVisibleValue)
struct privateStruct;
public:
explicit ProgressCircle(QWidget *parent = nullptr);
virtual ~ProgressCircle();
int value() const;
/**
* @brief maximum
* If maximum <= 0, widget shows infinite process;
* @return
*/
int maximum() const;
/**
* @brief innerRadius = [0.0 .. 1.0]
* @return
*/
qreal innerRadius() const;
/**
* @brief outerRadius = [0.0 .. 1.0]
* @return
*/
qreal outerRadius() const;
QColor color() const;
void animationStart();
void animationFinished();
void animationPaused();
void startInfiniteAnimation();
void stopInfiniteAnimation();
void pauseInfiniteAnimation();
public slots:
void setValue(int value);
void setMaximum(int maximum);
void setInnerRadius(qreal innerRadius);
void setOuterRadius(qreal outerRadius);
void setColor(QColor color);
signals:
void valueChanged(int);
void maximumChanged(int);
protected:
void paintEvent(QPaintEvent *);
private slots:
void setInfiniteAnimationValue(qreal value);
void setVisibleValue(int value);
private:
void initAnimation();
QString key() const;
QPixmap generatePixmap() const;
qreal infiniteAnimationValue() const;
int visibleValue() const;
private:
QScopedPointer<privateStruct> d;
};
-------------------------------------
.cpp
/////////////////////////////////////////////////////////////////////////////
// Date of creation: 04.07.2013
// Creator: Alexander Egorov aka mofr
// Modifier : sp.Park 2018.10.30
// Authors: mofr
/////////////////////////////////////////////////////////////////////////////
#include "ProgressCircle.h"
#include <QPainter>
#include <QPixmapCache>
struct ProgressCircle::privateStruct
{
qreal mInnerRadius;
qreal mOuterRadius;
qreal mInfiniteAnimationValue;
QColor mColor;
QPropertyAnimation mValueAnimation;
QPropertyAnimation mInfiniteAnimation;
int mValue = 0;
int mMaximum = 0;
int mVisibleValue = 0;
bool mIsInfinite = true;
};
ProgressCircle::ProgressCircle(QWidget *parent) :
QWidget(parent),
d(new privateStruct)
{
d->mValueAnimation.setTargetObject(this);
d->mValueAnimation.setPropertyName("visibleValue");
d->mInfiniteAnimation.setTargetObject(this);
d->mInfiniteAnimation.setPropertyName("infiniteAnimationValue");
d->mInfiniteAnimation.setLoopCount(-1);//infinite
d->mInfiniteAnimation.setDuration(1000);
d->mInfiniteAnimation.setStartValue(0.0);
d->mInfiniteAnimation.setEndValue(1.0);
}
ProgressCircle::~ProgressCircle()
{
}
int ProgressCircle::value() const
{
return d->mValue;
}
int ProgressCircle::maximum() const
{
return d->mMaximum;
}
qreal ProgressCircle::innerRadius() const
{
return d->mInnerRadius;
}
qreal ProgressCircle::outerRadius() const
{
return d->mOuterRadius;
}
QColor ProgressCircle::color() const
{
return d->mColor;
}
void ProgressCircle::initAnimation()
{
d->mColor = QColor(110, 190, 235);
d->mInnerRadius = 0.6;
d->mOuterRadius = 1.0;
QPropertyAnimation * progressCircleAnimation = new QPropertyAnimation(this, "outerRadius", this);
progressCircleAnimation->setDuration(1000);
progressCircleAnimation->setEasingCurve(QEasingCurve::OutQuad);
progressCircleAnimation->setStartValue(0.0);
progressCircleAnimation->setEndValue(d->mOuterRadius);
progressCircleAnimation->start(QAbstractAnimation::DeleteWhenStopped);
progressCircleAnimation = new QPropertyAnimation(this, "innerRadius", this);
progressCircleAnimation->setDuration(500);
progressCircleAnimation->setEasingCurve(QEasingCurve::OutQuad);
progressCircleAnimation->setEndValue(d->mInnerRadius);
progressCircleAnimation->start(QAbstractAnimation::DeleteWhenStopped);
progressCircleAnimation = new QPropertyAnimation(this, "color", this);
progressCircleAnimation->setDuration(500);
progressCircleAnimation->setEasingCurve(QEasingCurve::OutQuad);
progressCircleAnimation->setEndValue(d->mColor);
progressCircleAnimation->start(QAbstractAnimation::DeleteWhenStopped);
}
void ProgressCircle::animationStart()
{
this->setValue(0);
this->initAnimation();
d->mIsInfinite = true;
d->mInfiniteAnimation.start();
}
void ProgressCircle::animationFinished()
{
d->mIsInfinite = false;
d->mInfiniteAnimation.stop();
this->setValue(this->maximum());
QPropertyAnimation * animation = new QPropertyAnimation(this, "outerRadius", this);
animation->setDuration(1000);
animation->setEasingCurve(QEasingCurve::OutQuad);
animation->setEndValue(0.5);
animation->start(QAbstractAnimation::DeleteWhenStopped);
animation = new QPropertyAnimation(this, "innerRadius", this);
animation->setDuration(500);
animation->setEasingCurve(QEasingCurve::OutQuad);
animation->setEndValue(0.0);
animation->start(QAbstractAnimation::DeleteWhenStopped);
QColor color(155,219,58);
animation = new QPropertyAnimation(this, "color", this);
animation->setDuration(500);
animation->setEasingCurve(QEasingCurve::OutQuad);
animation->setEndValue(color);
animation->start(QAbstractAnimation::DeleteWhenStopped);
}
void ProgressCircle::animationPaused()
{
QPropertyAnimation * animation = new QPropertyAnimation(this, "outerRadius", this);
animation->setDuration(1000);
animation->setEasingCurve(QEasingCurve::OutQuad);
animation->setEndValue(0.5);
animation->start(QAbstractAnimation::DeleteWhenStopped);
animation = new QPropertyAnimation(this, "innerRadius", this);
animation->setDuration(500);
animation->setEasingCurve(QEasingCurve::OutQuad);
animation->setEndValue(0.0);
animation->start(QAbstractAnimation::DeleteWhenStopped);
QColor color(255,100,100);
animation = new QPropertyAnimation(this, "color", this);
animation->setDuration(500);
animation->setEasingCurve(QEasingCurve::OutQuad);
animation->setEndValue(color);
animation->start(QAbstractAnimation::DeleteWhenStopped);
}
void ProgressCircle::startInfiniteAnimation()
{
this->animationStart();
}
void ProgressCircle::stopInfiniteAnimation()
{
this->animationFinished();
}
void ProgressCircle::pauseInfiniteAnimation()
{
d->mInfiniteAnimation.pause();
}
void ProgressCircle::setValue(int value)
{
if(d->mIsInfinite == true)
return;
if(value < 0)
value = 0;
if((qFuzzyCompare(d->mInnerRadius, 0.6) == false) || (qFuzzyCompare(d->mOuterRadius, 1.0) == false))
{
this->initAnimation();
if(this->maximum() == 0)
this->setMaximum(100);
}
if(d->mValue != value)
{
d->mValueAnimation.stop();
d->mValueAnimation.setEndValue(value);
d->mValueAnimation.setDuration(250);
d->mValueAnimation.start();
d->mValue = value;
emit valueChanged(value);
}
}
void ProgressCircle::setMaximum(int maximum)
{
if(maximum < 0)
maximum = 0;
if(d->mMaximum != maximum)
{
d->mMaximum = maximum;
this->update();
emit maximumChanged(maximum);
}
}
void ProgressCircle::setInnerRadius(qreal innerRadius)
{
if(innerRadius > 1.0)
innerRadius = 1.0;
if(innerRadius < 0.0)
innerRadius = 0.0;
if(d->mInnerRadius != innerRadius)
{
d->mInnerRadius = innerRadius;
this->update();
}
}
void ProgressCircle::setOuterRadius(qreal outerRadius)
{
if(outerRadius > 1.0)
outerRadius = 1.0;
if(outerRadius < 0.0)
outerRadius = 0.0;
if(d->mOuterRadius != outerRadius)
{
d->mOuterRadius = outerRadius;
this->update();
}
}
void ProgressCircle::setColor(QColor color)
{
if(color != d->mColor)
{
d->mColor = color;
this->update();
}
}
QRectF squared(QRectF rect)
{
if(rect.width() > rect.height())
{
qreal diff = rect.width() - rect.height();
return rect.adjusted(diff/2, 0, -diff/2, 0);
}
else
{
qreal diff = rect.height() - rect.width();
return rect.adjusted(0, diff/2, 0, -diff/2);
}
}
void ProgressCircle::paintEvent(QPaintEvent *)
{
QPixmap pixmap;
if (!QPixmapCache::find(key(), pixmap))
{
pixmap = generatePixmap();
QPixmapCache::insert(key(), pixmap);
}
// Draw pixmap at center of item
QPainter painter(this);
painter.drawPixmap( 0.5 * ( width() - pixmap.width() ), 0.5 * ( height() - pixmap.height() ), pixmap );
}
void ProgressCircle::setInfiniteAnimationValue(qreal value)
{
d->mInfiniteAnimationValue = value;
this->update();
}
void ProgressCircle::setVisibleValue(int value)
{
if(d->mVisibleValue != value)
{
d->mVisibleValue = value;
this->update();
}
}
QString ProgressCircle::key() const
{
return QString("%1,%2,%3,%4,%5,%6,%7,%8")
.arg(d->mInfiniteAnimationValue)
.arg(d->mVisibleValue)
.arg(d->mMaximum)
.arg(d->mInnerRadius)
.arg(d->mOuterRadius)
.arg(this->width())
.arg(this->height())
.arg(d->mColor.rgb());
}
QPixmap ProgressCircle::generatePixmap() const
{
QPixmap pixmap(squared(rect()).size().toSize());
pixmap.fill(QColor(0,0,0,0));
QPainter painter(&pixmap);
painter.setRenderHint(QPainter::Antialiasing, true);
QRectF rect = pixmap.rect().adjusted(1,1,-1,-1);
qreal margin = rect.width()*(1.0 - d->mOuterRadius)/2.0;
rect.adjust(margin,margin,-margin,-margin);
qreal innerRadius = d->mInnerRadius*rect.width()/2.0;
//background grey circle
painter.setBrush(QColor(225,225,225));
painter.setPen(QColor(225,225,225));
painter.drawPie(rect, 0, 360*16);
painter.setBrush(d->mColor);
painter.setPen(d->mColor);
if(d->mIsInfinite == true)
{
//draw as infinite process
int startAngle = (-d->mInfiniteAnimationValue) * 360 * 16;
int spanAngle = 0.15 * 360 * 16;
painter.drawPie(rect, startAngle, spanAngle);
}
else
{
int value = qMin(d->mVisibleValue, d->mMaximum);
int startAngle = 90 * 16;
int spanAngle = -qreal(value) * 360 * 16 / d->mMaximum;
painter.drawPie(rect, startAngle, spanAngle);
}
//inner circle and frame
painter.setBrush(QColor(255,255,255));
painter.setPen(QColor(0,0,0, 60));
painter.drawEllipse(rect.center(), innerRadius, innerRadius);
//outer frame
painter.drawArc(rect, 0, 360*16);
return pixmap;
}
qreal ProgressCircle::infiniteAnimationValue() const
{
return d->mInfiniteAnimationValue;
}
int ProgressCircle::visibleValue() const
{
return d->mVisibleValue;
}
해당코드는 Git 허브에서 원본소스를 가져왔으며
제가 수정하였습니다.
문제시 삭제하겠습니다.
코드 수정 배포시
원제작자, 수정자 남겨주시기바랍니다.
사용법은 위젯위에 Promote하시던가 그냥 만들어서 setvalue같은거 써보시면 됍니다 :)