add ripple

This commit is contained in:
lazerpants 2016-03-18 17:36:02 +03:00
parent 473999a5a8
commit f3a4e06a1b
7 changed files with 212 additions and 4 deletions

View File

@ -1,15 +1,18 @@
#include <QDebug>
#include <QStylePainter>
#include <QStyleOptionButton>
#include <QMouseEvent>
#include "flatbutton.h"
FlatButton::FlatButton(QWidget *parent)
: QAbstractButton(parent)
: QAbstractButton(parent),
_overlay(new RippleOverlay(this))
{
}
FlatButton::FlatButton(const QString &text, QWidget *parent)
: QAbstractButton(parent)
: QAbstractButton(parent),
_overlay(new RippleOverlay(this))
{
setText(text);
}
@ -18,6 +21,13 @@ FlatButton::~FlatButton()
{
}
void FlatButton::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event)
updateOverlayGeometry();
}
void FlatButton::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
@ -45,6 +55,18 @@ void FlatButton::paintEvent(QPaintEvent *event)
}
}
void FlatButton::mousePressEvent(QMouseEvent *event)
{
_overlay->addRipple(event->pos());
}
void FlatButton::mouseReleaseEvent(QMouseEvent *event)
{
Q_UNUSED(event)
emit clicked();
}
void FlatButton::enterEvent(QEvent *event)
{
Q_UNUSED(event)

View File

@ -2,6 +2,7 @@
#define FLATBUTTON_H
#include <QAbstractButton>
#include "rippleoverlay.h"
class FlatButton : public QAbstractButton
{
@ -13,9 +14,17 @@ public:
~FlatButton();
protected:
void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE;
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void enterEvent(QEvent *event) Q_DECL_OVERRIDE;
void leaveEvent(QEvent *event) Q_DECL_OVERRIDE;
private:
inline void updateOverlayGeometry() { _overlay->setGeometry(rect()); }
RippleOverlay *const _overlay;
};
#endif // FLATBUTTON_H

View File

@ -27,7 +27,9 @@ SOURCES += main.cpp\
tab.cpp \
tabs.cpp \
textfield.cpp \
table.cpp
table.cpp \
ripple.cpp \
rippleoverlay.cpp
HEADERS += mainwindow.h \
style.h \
@ -43,4 +45,6 @@ HEADERS += mainwindow.h \
tab.h \
tabs.h \
textfield.h \
table.h
table.h \
ripple.h \
rippleoverlay.h

32
ripple.cpp Normal file
View File

@ -0,0 +1,32 @@
#include "ripple.h"
Ripple::Ripple(const QPoint &center, QObject *parent)
: QObject(parent),
_radiusAnimation(animate("radius")),
_opacityAnimation(animate("opacity")),
_radius(0),
_opacity(0),
_center(center)
{
connect(&_group, SIGNAL(finished()), this, SIGNAL(finished()));
setOpacityStartValue(0.5);
setOpacityEndValue(0);
setRadiusStartValue(0);
setRadiusEndValue(300);
}
Ripple::~Ripple()
{
}
QPropertyAnimation *Ripple::animate(const QByteArray &property)
{
QPropertyAnimation *animation = new QPropertyAnimation;
animation->setPropertyName(property);
animation->setEasingCurve(QEasingCurve::OutCubic);
animation->setTargetObject(this);
animation->setDuration(700);
_group.addAnimation(animation);
return animation;
}

56
ripple.h Normal file
View File

@ -0,0 +1,56 @@
#ifndef RIPPLE_H
#define RIPPLE_H
#include <QObject>
#include <QPoint>
#include <QParallelAnimationGroup>
#include <QPropertyAnimation>
class Ripple : public QObject
{
Q_OBJECT
Q_PROPERTY(qreal radius WRITE setRadius READ radius)
Q_PROPERTY(qreal opacity WRITE setOpacity READ opacity)
public:
explicit Ripple(const QPoint &center, QObject *parent = 0);
~Ripple();
inline void setRadius(qreal radius) { _radius = radius; emit valueChanged(); }
inline qreal radius() const { return _radius; }
inline void setOpacity(qreal opacity) { _opacity = opacity; emit valueChanged(); }
inline qreal opacity() const { return _opacity; }
inline const QPoint &center() const { return _center; }
inline void setDuration(int duration)
{
_radiusAnimation->setDuration(duration);
_opacityAnimation->setDuration(duration);
}
inline void setOpacityStartValue(qreal value) { _opacityAnimation->setStartValue(value); }
inline void setOpacityEndValue(qreal value) { _opacityAnimation->setEndValue(value); }
inline void setRadiusStartValue(qreal value) { _radiusAnimation->setStartValue(value); }
inline void setRadiusEndValue(qreal value) { _radiusAnimation->setEndValue(value); }
inline void startAnimation() { _group.start(); }
signals:
void valueChanged();
void finished();
private:
QPropertyAnimation *animate(const QByteArray &property);
QParallelAnimationGroup _group;
QPropertyAnimation *const _radiusAnimation;
QPropertyAnimation *const _opacityAnimation;
qreal _radius;
qreal _opacity;
QPoint _center;
};
#endif // RIPPLE_H

57
rippleoverlay.cpp Normal file
View File

@ -0,0 +1,57 @@
#include <QDebug>
#include <QPainter>
#include "rippleoverlay.h"
#include "ripple.h"
RippleOverlay::RippleOverlay(QWidget *parent)
: QWidget(parent)
{
setAttribute(Qt::WA_TransparentForMouseEvents);
setAttribute(Qt::WA_NoSystemBackground);
}
RippleOverlay::~RippleOverlay()
{
}
void RippleOverlay::addRipple(const QPoint &position, qreal radius)
{
Ripple *ripple = new Ripple(position);
ripple->setRadiusEndValue(radius);
ripples.push_back(ripple);
connect(ripple, SIGNAL(valueChanged()), this, SLOT(update()));
connect(ripple, SIGNAL(finished()), this, SLOT(deleteRipple()));
ripple->startAnimation();
}
void RippleOverlay::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event)
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
QBrush brush;
brush.setColor(Qt::black);
brush.setStyle(Qt::SolidPattern);
painter.setBrush(brush);
QList<Ripple *>::const_iterator i;
for (i = ripples.begin(); i != ripples.end(); ++i)
{
const Ripple *ripple = *i;
const qreal radius = ripple->radius();
const QPointF &center = ripple->center();
painter.setOpacity(ripple->opacity());
painter.drawEllipse(center, radius, radius);
}
}
void RippleOverlay::deleteRipple()
{
if (ripples.isEmpty()) {
qWarning() << "RippleOverlay::deleteRipple was called when no active ripple.";
return;
}
ripples.takeFirst()->deleteLater();
}

28
rippleoverlay.h Normal file
View File

@ -0,0 +1,28 @@
#ifndef RIPPLEOVERLAY_H
#define RIPPLEOVERLAY_H
#include <QWidget>
class Ripple;
class RippleOverlay : public QWidget
{
Q_OBJECT
public:
explicit RippleOverlay(QWidget *parent = 0);
~RippleOverlay();
void addRipple(const QPoint &position, qreal radius = 300);
protected:
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
protected slots:
void deleteRipple();
private:
QList<Ripple *> ripples;
};
#endif // RIPPLEOVERLAY_H