1 #include "qswitchcontrol.h"
2 
3 #include <QPushButton>
4 #include <QPropertyAnimation>
5 #include <QStyleOption>
6 #include <QPainter>
7 
8 static const QSize FrameSize = QSize(68, 30);
9 static const QSize SwitchSize = QSize (26, 26);
10 static const int SwitchOffset = (FrameSize.height() - SwitchSize.height()) / 2;
11 
12 static const QString CustomFrameOnStlye = QString("QAbstractButton { border: none; border-radius: %1; background-color: #4697D9;}").arg(FrameSize.height() / 2);
13 static const QString CustomFrameOffStlye = QString("QAbstractButton { border: none; border-radius: %1; background-color: #6f80ab;}").arg(FrameSize.height() / 2);
14 static const QString CustomButtonStlye = QString("QPushButton { min-width: 0em; border-radius: %1; background-color: white;}").arg(SwitchSize.height() / 2);
15 
QSwitchControl(QWidget * parent)16 QSwitchControl::QSwitchControl(QWidget *parent):
17     QAbstractButton(parent)
18 {
19     this->setFixedSize(FrameSize);
20 
21     pbSwitch = new QPushButton(this);
22     pbSwitch->setFixedSize(SwitchSize);
23     pbSwitch->setStyleSheet(CustomButtonStlye);
24 
25     animation = new QPropertyAnimation(pbSwitch, "geometry", this);
26     animation->setDuration(200);
27 
28     connect(this, &QSwitchControl::mouseClicked, this, &QSwitchControl::onStatusChanged);
29     connect(pbSwitch, &QPushButton::clicked, this, &QSwitchControl::onStatusChanged);
30     setCheckable(true);
31     setChecked(false);
32 }
33 
setChecked(bool checked)34 void QSwitchControl::setChecked(bool checked)
35 {
36     if(checked)
37     {
38         pbSwitch->move(this->width() - pbSwitch->width() - SwitchOffset, this->y() + SwitchOffset);
39         this->setStyleSheet(CustomFrameOnStlye);
40     }
41     else
42     {
43         pbSwitch->move(this->x() + SwitchOffset, this->y() + SwitchOffset);
44         this->setStyleSheet(CustomFrameOffStlye);
45     }
46 
47     QAbstractButton::setChecked(checked);
48 }
49 
onStatusChanged()50 void QSwitchControl::onStatusChanged()
51 {
52     bool checked = !isChecked();
53 
54     QRect currentGeometry(pbSwitch->x(), pbSwitch->y(), pbSwitch->width(), pbSwitch->height());
55 
56     if(animation->state() == QAbstractAnimation::Running)
57         animation->stop();
58 
59     if(checked)
60     {
61         this->setStyleSheet(CustomFrameOnStlye);
62 
63         animation->setStartValue(currentGeometry);
64         animation->setEndValue(QRect(this->width() - pbSwitch->width() - SwitchOffset, pbSwitch->y(), pbSwitch->width(), pbSwitch->height()));
65     }
66     else
67     {
68         this->setStyleSheet(CustomFrameOffStlye);
69 
70         animation->setStartValue(currentGeometry);
71         animation->setEndValue(QRect(SwitchOffset, pbSwitch->y(), pbSwitch->width(), pbSwitch->height()));
72     }
73     animation->start();
74 
75     setChecked(checked);
76     Q_EMIT clicked(checked);
77 }
78 
mousePressEvent(QMouseEvent *)79 void QSwitchControl::mousePressEvent(QMouseEvent *)
80 {
81     Q_EMIT mouseClicked();
82 }
83 
paintEvent(QPaintEvent *)84 void QSwitchControl::paintEvent(QPaintEvent *)
85 {
86     QStyleOption opt;
87     opt.init(this);
88     QPainter p(this);
89     style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
90 }
91