This commit is contained in:
laserpants 2016-05-09 23:32:16 +03:00
parent eb7b7dfda1
commit d881c4c898
5 changed files with 403 additions and 111 deletions

View File

@ -11,67 +11,105 @@ Slider::Slider(QWidget *parent)
: QAbstractSlider(parent),
d_ptr(new SliderPrivate(this))
{
QPropertyAnimation *animation;
d_ptr->init(this);
animation = new QPropertyAnimation;
setFocusPolicy(Qt::StrongFocus);
animation->setPropertyName("haloScaleFactor");
animation->setTargetObject(this);
animation->setStartValue(0.8);
animation->setEndValue(1);
animation->setDuration(900);
animation->setEasingCurve(QEasingCurve::InOutQuad);
QSizePolicy sp(QSizePolicy::Expanding, QSizePolicy::Fixed);
if (orientation() == Qt::Vertical)
sp.transpose();
setSizePolicy(sp);
setAttribute(Qt::WA_WState_OwnSizePolicy, false);
d_ptr->haloAnimation->addAnimation(animation);
animation = new QPropertyAnimation;
animation->setPropertyName("haloScaleFactor");
animation->setTargetObject(this);
animation->setStartValue(1);
animation->setEndValue(0.8);
animation->setDuration(900);
animation->setEasingCurve(QEasingCurve::InOutQuad);
d_ptr->haloAnimation->addAnimation(animation);
d_ptr->haloAnimation->setLoopCount(-1);
d_ptr->haloAnimation->start();
connect(this, SIGNAL(actionTriggered(int)), this, SLOT(handleAction(int)));
// connect(this, SIGNAL(actionTriggered(int)), this, SLOT(handleAction(int)));
}
Slider::~Slider()
{
}
void Slider::setHaloScaleFactor(qreal factor)
QSize Slider::minimumSizeHint() const
{
return QSize(20, 20);
}
int Slider::thumbOffset() const
{
return Style::sliderPositionFromValue(
minimum(),
maximum(),
sliderPosition(),
Qt::Horizontal == orientation()
? rect().width() - 20 : rect().height() - 20,
false);
}
void Slider::setThumbSize(qreal size)
{
Q_D(Slider);
d->haloScaleFactor = factor;
d->thumbSize = size;
update();
}
qreal Slider::haloScaleFactor() const
qreal Slider::thumbSize() const
{
Q_D(const Slider);
return d->haloScaleFactor;
return d->thumbSize;
}
void Slider::handleAction(int action)
void Slider::setThumbPenWidth(qreal width)
{
Q_D(Slider);
if (!d->step)
return;
d->thumbPenWidth = width;
update();
}
if ((SliderPageStepAdd == action && sliderPosition() > d->stepTo) ||
(SliderPageStepSub == action && sliderPosition() < d->stepTo))
{
setSliderPosition(d->stepTo);
qreal Slider::thumbPenWidth() const
{
Q_D(const Slider);
return d->thumbPenWidth;
}
void Slider::setThumbColor(const QColor &color)
{
Q_D(Slider);
d->thumbColor = color;
update();
}
QColor Slider::thumbColor() const
{
Q_D(const Slider);
return d->thumbColor;
}
void Slider::sliderChange(SliderChange change)
{
Q_D(Slider);
if (SliderOrientationChange == change) {
QSizePolicy sp(QSizePolicy::Expanding, QSizePolicy::Fixed);
if (orientation() == Qt::Vertical)
sp.transpose();
setSizePolicy(sp);
} else if (SliderValueChange == change) {
if (minimum() == value()) {
triggerAction(SliderToMinimum);
emit changedToMinimum();
} else if (maximum() == value()) {
triggerAction(SliderToMaximum);
} else if (minimum() == d->oldValue) {
emit changedFromMinimum();
}
d->oldValue = value();
}
QAbstractSlider::sliderChange(change);
}
void Slider::paintEvent(QPaintEvent *event)
@ -83,10 +121,12 @@ void Slider::paintEvent(QPaintEvent *event)
QPainter painter(this);
d->paintTrack(&painter);
d->paintHalo(&painter);
d->paintThumb(&painter);
#ifdef DEBUG_LAYOUT
if (hasFocus())
painter.drawRect(rect().adjusted(0, 0, -1, -1));
QPen pen;
pen.setColor(Qt::red);
pen.setWidth(1);
@ -94,10 +134,6 @@ void Slider::paintEvent(QPaintEvent *event)
painter.setPen(pen);
painter.setBrush(Qt::NoBrush);
painter.drawRect(rect().adjusted(0, 0, -1, -1));
painter.setFont(QFont("monospace", 8));
painter.drawText(8, 18, "Value: " % QString::number(value()));
painter.drawText(8, 36, "Position: " % QString::number(sliderPosition()));
#endif
}
@ -105,10 +141,12 @@ void Slider::mouseMoveEvent(QMouseEvent *event)
{
Q_D(Slider);
if (isSliderDown()) {
if (isSliderDown())
{
setSliderPosition(d->valueFromPosition(event->pos()));
} else {
}
else
{
QRectF track(d->trackGeometry().adjusted(-2, -2, 2, 2));
if (track.contains(event->pos()) != d->hoverTrack) {
@ -142,19 +180,15 @@ void Slider::mousePressEvent(QMouseEvent *event)
return;
}
QRectF track(d->trackGeometry().adjusted(-2, -2, 2, 2));
d->step = true;
d->stepTo = d->valueFromPosition(pos);
if (track.contains(pos)) {
d->step = true;
d->stepTo = d->valueFromPosition(pos);
SliderAction action = d->stepTo > sliderPosition()
? SliderPageStepAdd
: SliderPageStepSub;
SliderAction action = d->stepTo > sliderPosition()
? SliderPageStepAdd
: SliderPageStepSub;
triggerAction(action);
setRepeatAction(action, 200);
}
triggerAction(action);
setRepeatAction(action);
}
void Slider::mouseReleaseEvent(QMouseEvent *event)

View File

@ -10,19 +10,34 @@ class Slider : public QAbstractSlider
{
Q_OBJECT
Q_PROPERTY(qreal haloScaleFactor WRITE setHaloScaleFactor READ haloScaleFactor)
Q_PROPERTY(qreal thumbSize WRITE setThumbSize READ thumbSize)
Q_PROPERTY(qreal thumbPenWidth WRITE setThumbPenWidth READ thumbPenWidth)
Q_PROPERTY(QColor thumbColor WRITE setThumbColor READ thumbColor)
public:
explicit Slider(QWidget *parent = 0);
~Slider();
void setHaloScaleFactor(qreal factor);
qreal haloScaleFactor() const;
QSize minimumSizeHint() const;
protected slots:
void handleAction(int action);
int thumbOffset() const;
void setThumbSize(qreal size);
qreal thumbSize() const;
void setThumbPenWidth(qreal width);
qreal thumbPenWidth() const;
void setThumbColor(const QColor &color);
QColor thumbColor() const;
signals:
void changedToMinimum();
void changedFromMinimum();
protected:
void sliderChange(SliderChange change) Q_DECL_OVERRIDE;
void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;
void mouseMoveEvent(QMouseEvent *event) Q_DECL_OVERRIDE;
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;

View File

@ -1,12 +1,101 @@
// @todo -- separate decl. and impl.
// inverse mode
// paint track differently left of thumb
// direct click mode (mode thumb to click pos)
// paint thumb in halo widget
#ifndef SLIDER_P_H
#define SLIDER_P_H
#include "slider.h"
#include <QPainter>
#include <QSequentialAnimationGroup>
#include <QPropertyAnimation>
#include <QStateMachine>
#include <QEventTransition>
#include <QSignalTransition>
#include <QDebug>
#include "lib/style.h"
#define THUMB_OUTER_SIZE 35
#define THUMB_OUTER_SIZE 20
class Halo : public QWidget
{
Q_OBJECT
Q_PROPERTY(qreal size WRITE setSize READ size)
public:
Halo(Slider *slider)
: QWidget(slider->parentWidget()),
slider(slider),
_size(0)
{
slider->installEventFilter(this);
setAttribute(Qt::WA_TransparentForMouseEvents, true);
connect(slider, SIGNAL(sliderMoved(int)), this, SLOT(update()));
connect(slider, SIGNAL(valueChanged(int)), this, SLOT(update()));
}
~Halo()
{
}
inline void setSize(qreal size)
{
_size = size;
update();
}
inline qreal size() const { return _size; }
protected:
bool eventFilter(QObject *obj, QEvent *event)
{
if (QEvent::ParentChange == event->type()) {
setParent(slider->parentWidget());
}
return QWidget::eventFilter(obj, event);
}
void paintEvent(QPaintEvent *event)
{
QPainter painter(this);
QBrush brush;
brush.setStyle(Qt::SolidPattern);
brush.setColor(QColor(0, 0, 0, 20));
painter.setBrush(brush);
painter.setPen(Qt::NoPen);
painter.setRenderHint(QPainter::Antialiasing);
QPointF disp = Qt::Horizontal == slider->orientation()
? QPointF(THUMB_OUTER_SIZE/2 + slider->thumbOffset(),
slider->height()/2)
: QPointF(slider->width()/2,
THUMB_OUTER_SIZE/2 + slider->thumbOffset());
QRectF halo((slider->pos() - QPointF(_size, _size)/2) + disp,
QSize(_size, _size));
painter.drawEllipse(halo);
#ifdef DEBUG_LAYOUT
QPen pen;
pen.setColor(Qt::red);
pen.setWidth(2);
painter.setPen(pen);
painter.setBrush(Qt::NoBrush);
painter.drawRect(rect().adjusted(0, 0, -2, -2));
#endif
QWidget::paintEvent(event);
}
private:
const Slider *const slider;
qreal _size;
};
class SliderPrivate
{
@ -16,16 +105,155 @@ class SliderPrivate
public:
SliderPrivate(Slider *parent)
: q_ptr(parent),
haloAnimation(new QSequentialAnimationGroup(parent)),
haloScaleFactor(1),
halo(new Halo(parent)),
hoverTrack(false),
hoverThumb(false),
step(false),
stepTo(0)
stepTo(0),
oldValue(parent->value()),
thumbSize(11),
thumbPenWidth(0),
thumbColor(Qt::white)
{
parent->setMouseTracking(true);
}
void init(Slider *slider)
{
QState *s1 = new QState(QState::ParallelStates);
QState *s11 = new QState(s1);
QState *inactiveState = new QState(s11);
QState *focusState = new QState(s11);
QState *pulseState = new QState(focusState);
QState *pulse2State = new QState(focusState);
QState *downState = new QState(s11);
focusState->setInitialState(pulseState);
inactiveState->assignProperty(halo, "size", 0);
pulseState->assignProperty(halo, "size", 35);
pulse2State->assignProperty(halo, "size", 28);
downState->assignProperty(halo, "size", 0);
inactiveState->assignProperty(slider, "thumbSize", 11);
focusState->assignProperty(slider, "thumbSize", 11);
downState->assignProperty(slider, "thumbSize", 17);
machine.addState(s1);
s11->setInitialState(inactiveState);
//machine.addState(inactiveState);
//machine.addState(focusState);
//machine.addState(downState);
//machine.setInitialState(inactiveState);
machine.setInitialState(s1);
QAbstractTransition *transition;
QPropertyAnimation *animation;
// Show halo on focus in
transition = new QEventTransition(slider, QEvent::FocusIn);
transition->setTargetState(focusState);
animation = new QPropertyAnimation(halo, "size");
transition->addAnimation(animation);
inactiveState->addTransition(transition);
// Hide halo on focus out
transition = new QEventTransition(slider, QEvent::FocusOut);
transition->setTargetState(inactiveState);
animation = new QPropertyAnimation(halo, "size");
transition->addAnimation(animation);
focusState->addTransition(transition);
// Pulse in
transition = new QSignalTransition(pulseState, SIGNAL(propertiesAssigned()));
transition->setTargetState(pulse2State);
animation = new QPropertyAnimation(halo, "size");
animation->setEasingCurve(QEasingCurve::InOutSine);
animation->setDuration(1000);
transition->addAnimation(animation);
pulseState->addTransition(transition);
// Pulse out
transition = new QSignalTransition(pulse2State, SIGNAL(propertiesAssigned()));
transition->setTargetState(pulseState);
animation = new QPropertyAnimation(halo, "size");
animation->setEasingCurve(QEasingCurve::InOutSine);
animation->setDuration(1000);
transition->addAnimation(animation);
pulse2State->addTransition(transition);
// Slider pressed
transition = new QSignalTransition(slider, SIGNAL(sliderPressed()));
transition->setTargetState(downState);
transition->addAnimation(new QPropertyAnimation(slider, "thumbSize"));
transition->addAnimation(new QPropertyAnimation(halo, "size"));
focusState->addTransition(transition);
// Slider released
transition = new QSignalTransition(slider, SIGNAL(sliderReleased()));
transition->setTargetState(focusState);
transition->addAnimation(new QPropertyAnimation(slider, "thumbSize"));
transition->addAnimation(new QPropertyAnimation(halo, "size"));
downState->addTransition(transition);
//
QState *s12 = new QState(s1);
QState *t1 = new QState(s12);
QState *t2 = new QState(s12);
t1->assignProperty(slider, "thumbColor", QColor(0, 0, 0));
t1->assignProperty(slider, "thumbPenWidth", 0);
t2->assignProperty(slider, "thumbColor", QColor(255, 255, 255));
t2->assignProperty(slider, "thumbPenWidth", 1.5);
//machine.addState(t1);
//machine.addState(t2);
//machine.addState(s12);
s12->setInitialState(t1);
transition = new QSignalTransition(slider, SIGNAL(changedToMinimum()));
transition->setTargetState(t2);
animation = new QPropertyAnimation(slider, "thumbColor");
animation->setDuration(700);
transition->addAnimation(animation);
animation = new QPropertyAnimation(slider, "thumbPenWidth");
animation->setDuration(700);
transition->addAnimation(animation);
t1->addTransition(transition);
transition = new QSignalTransition(slider, SIGNAL(changedFromMinimum()));
transition->setTargetState(t1);
animation = new QPropertyAnimation(slider, "thumbColor");
animation->setDuration(700);
transition->addAnimation(animation);
animation = new QPropertyAnimation(slider, "thumbPenWidth");
animation->setDuration(700);
transition->addAnimation(animation);
t2->addTransition(transition);
machine.start();
}
QRectF trackGeometry() const
{
Q_Q(const Slider);
@ -63,58 +291,36 @@ public:
{
Q_Q(const Slider);
const int span = Qt::Horizontal == q->orientation()
? q->rect().width() - THUMB_OUTER_SIZE
: q->rect().height() - THUMB_OUTER_SIZE;
const int pos = Style::sliderPositionFromValue(
q->minimum(),
q->maximum(),
q->sliderPosition(),
span,
false);
return Qt::Horizontal == q->orientation()
? QRectF(pos, q->rect().height()/2 - THUMB_OUTER_SIZE/2,
? QRectF(q->thumbOffset(), q->rect().height()/2 - THUMB_OUTER_SIZE/2,
THUMB_OUTER_SIZE, THUMB_OUTER_SIZE)
: QRectF(q->rect().width()/2 - THUMB_OUTER_SIZE/2, pos,
: QRectF(q->rect().width()/2 - THUMB_OUTER_SIZE/2, q->thumbOffset(),
THUMB_OUTER_SIZE, THUMB_OUTER_SIZE);
}
void paintHalo(QPainter *painter)
{
painter->save();
QBrush brush;
brush.setStyle(Qt::SolidPattern);
brush.setColor(QColor(0, 0, 0, 20));
painter->setBrush(brush);
painter->setPen(Qt::NoPen);
painter->setRenderHint(QPainter::Antialiasing);
qreal size = THUMB_OUTER_SIZE * haloScaleFactor;
QRectF halo(0, 0, size, size);
halo.moveCenter(thumbGeometry().center());
painter->drawEllipse(halo);
painter->restore();
}
void paintThumb(QPainter *painter)
{
painter->drawRect(thumbGeometry().adjusted(0, 0, -1, -1));
/*
painter->save();
QBrush brush;
brush.setStyle(Qt::SolidPattern);
brush.setColor(QColor(0, 0, 0, 255));
brush.setColor(thumbColor);
painter->setBrush(brush);
if (thumbPenWidth) {
QPen pen;
pen.setWidthF(thumbPenWidth);
painter->setPen(pen);
} else {
painter->setPen(Qt::NoPen);
}
painter->setRenderHint(QPainter::Antialiasing);
QRectF thumb(0, 0, 11, 11);
QRectF thumb(0, 0, thumbSize, thumbSize);
thumb.moveCenter(thumbGeometry().center());
painter->drawEllipse(thumb);
@ -131,6 +337,7 @@ public:
painter->restore();
}
#endif
*/
}
int valueFromPosition(const QPoint &pos) const
@ -152,13 +359,16 @@ public:
}
Slider *const q_ptr;
QSequentialAnimationGroup *const haloAnimation;
qreal haloScaleFactor;
bool hoverTrack;
bool hoverThumb;
bool step;
int stepTo;
Halo *const halo;
QStateMachine machine;
bool hoverTrack;
bool hoverThumb;
bool step;
int stepTo;
int oldValue;
qreal thumbSize;
qreal thumbPenWidth;
QColor thumbColor;
};
#endif // SLIDER_P_H

View File

@ -13,7 +13,8 @@ SliderExamples::SliderExamples(QWidget *parent)
_edit(new QLineEdit),
_edit2(new QLineEdit),
_slider(new Slider),
_slider2(new Slider)
_slider2(new Slider),
__slider(new QSlider)
{
QLayout *mainLayout = widget()->layout();
@ -82,7 +83,7 @@ SliderExamples::SliderExamples(QWidget *parent)
QPushButton *button = new QPushButton("Change orientation");
_slider->setMinimumWidth(250);
//_slider->setMinimumWidth(250);
layout->addWidget(_slider);
layout->addWidget(button);
@ -105,6 +106,29 @@ SliderExamples::SliderExamples(QWidget *parent)
widget->setLayout(layout);
widget->setMinimumWidth(350);
QPushButton *button = new QPushButton("Change orientation");
//__slider->setMinimumWidth(250);
layout->addWidget(__slider);
layout->addWidget(button);
ExampleView *view = new ExampleView;
view->setWidget(widget);
Frame *frame = new Frame;
frame->setCodeSnippet("xxx");
frame->setWidget(view);
mainLayout->addWidget(frame);
connect(button, SIGNAL(pressed()), this, SLOT(flip2()));
}
{
QVBoxLayout *layout = new QVBoxLayout;
QWidget *widget = new QWidget;
widget->setLayout(layout);
widget->setMinimumWidth(350);
QHBoxLayout *hLayout = new QHBoxLayout;
QPushButton *button = new QPushButton("Update value");
hLayout->addWidget(_edit2);
@ -166,6 +190,12 @@ void SliderExamples::flip()
Qt::Vertical : Qt::Horizontal);
}
void SliderExamples::flip2()
{
__slider->setOrientation(Qt::Horizontal == __slider->orientation() ?
Qt::Vertical : Qt::Horizontal);
}
void SliderExamples::updateSliderValue()
{
_slider2->setValue(_edit2->text().toInt());

View File

@ -4,6 +4,7 @@
#include "examplelist.h"
class QLineEdit;
class QSlider;
class Slider;
class SliderExamples : public ExampleList
@ -17,6 +18,7 @@ public:
protected slots:
void updateValue(int value);
void flip();
void flip2();
void updateSliderValue();
private:
@ -24,6 +26,7 @@ private:
QLineEdit *const _edit2;
Slider *const _slider;
Slider *const _slider2;
QSlider *const __slider;
};
#endif // SLIDEREXAMPLES_H