diff --git a/src/widgets/assets/icons/bloom/switch_off.dci b/src/widgets/assets/icons/bloom/switch_off.dci
new file mode 100644
index 000000000..957f499a4
Binary files /dev/null and b/src/widgets/assets/icons/bloom/switch_off.dci differ
diff --git a/src/widgets/assets/icons/bloom/switch_on.dci b/src/widgets/assets/icons/bloom/switch_on.dci
new file mode 100644
index 000000000..20ec32c84
Binary files /dev/null and b/src/widgets/assets/icons/bloom/switch_on.dci differ
diff --git a/src/widgets/assets/icons/dtk-icon-theme.qrc b/src/widgets/assets/icons/dtk-icon-theme.qrc
index c4761d464..6d7924473 100644
--- a/src/widgets/assets/icons/dtk-icon-theme.qrc
+++ b/src/widgets/assets/icons/dtk-icon-theme.qrc
@@ -72,5 +72,7 @@
bloom/window_maximize.dci
bloom/window_minimize.dci
bloom/window_normal.dci
+ bloom/switch_on.dci
+ bloom/switch_off.dci
diff --git a/src/widgets/dstyle.cpp b/src/widgets/dstyle.cpp
index 234d0da24..d19556fc6 100644
--- a/src/widgets/dstyle.cpp
+++ b/src/widgets/dstyle.cpp
@@ -1,4 +1,4 @@
-// SPDX-FileCopyrightText: 2019 - 2023 UnionTech Software Technology Co., Ltd.
+// SPDX-FileCopyrightText: 2019 - 2024 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
@@ -1443,9 +1443,6 @@ void DStyle::drawControl(const QStyle *style, DStyle::ControlElement ce, const Q
DStyleOptionButton option = *btn;
option.dpalette = btn->dpalette;
option.rect = dstyle.subElementRect(SE_SwitchButtonGroove, opt, w);
- dstyle.drawPrimitive(PE_SwitchButtonGroove, &option, p, w);
- option.rect = dstyle.subElementRect(SE_SwitchButtonHandle, opt, w);
- dstyle.drawPrimitive(PE_SwitchButtonHandle, &option, p, w);
if (btn->state & State_HasFocus) {
QStyleOptionFocusRect fropt;
diff --git a/src/widgets/dswitchbutton.cpp b/src/widgets/dswitchbutton.cpp
index 273269737..9aed27f4d 100644
--- a/src/widgets/dswitchbutton.cpp
+++ b/src/widgets/dswitchbutton.cpp
@@ -3,15 +3,21 @@
// SPDX-License-Identifier: LGPL-3.0-or-later
#include "dswitchbutton.h"
-#include
-#include
#include "private/dswitchbutton_p.h"
-#include
+#include
+#include
+#include
+#include
+#include
+#include
DWIDGET_BEGIN_NAMESPACE
+constexpr int DCI_ICON_SIZE = 120;
+constexpr int TIMER_INTERVAL = 200;
+
/*!
@~english
@brief DSwitchButton::DSwitchButton implements a switch button
@@ -48,12 +54,16 @@ QSize DSwitchButton::sizeHint() const
*/
void DSwitchButton::paintEvent(QPaintEvent *e)
{
+ D_D(DSwitchButton);
Q_UNUSED(e);
DStylePainter painter(this);
DStyleOptionButton opt;
initStyleOption(&opt);
painter.drawControl(DStyle::CE_SwitchButton, opt);
+
+ painter.setRenderHint(QPainter::SmoothPixmapTransform);
+ painter.drawImage(rect().adjusted(2, -10, -2, 8), d->player.currentImage()); // 为了显示按钮的阴影所留的空白
}
/*!
@@ -88,6 +98,7 @@ void DSwitchButton::initStyleOption(DStyleOptionButton *option) const
DSwitchButtonPrivate::DSwitchButtonPrivate(DSwitchButton *qq)
: DObjectPrivate(qq)
+ , timer(new QTimer(qq))
{
}
@@ -102,13 +113,53 @@ void DSwitchButtonPrivate::init()
checked = false;
animationStartValue = 0;
animationEndValue = 1;
+ timer->setInterval(TIMER_INTERVAL);
D_Q(DSwitchButton);
q->setObjectName("DSwitchButton");
q->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
q->setCheckable(true);
- q->connect(q, &DSwitchButton::toggled, q, &DSwitchButton::checkedChanged);
+
+ auto initPlayer= [this, q]() {
+ DDciIcon icon = !checked ? DDciIcon::fromTheme("switch_on") : DDciIcon::fromTheme("switch_off");
+ player.setIcon(icon);
+ player.setMode(DDciIcon::Mode::Normal);
+ auto palette = DDciIconPalette::fromQPalette(q->palette());
+ player.setPalette(palette);
+ player.setDevicePixelRatio(qApp->devicePixelRatio());
+ player.setIconSize(DCI_ICON_SIZE);
+ player.setTheme(DGuiApplicationHelper::instance()->themeType() == DGuiApplicationHelper::DarkType
+ ? DDciIcon::Dark : DDciIcon::Light);
+ };
+
+ initPlayer();
+
+ q->connect(q, &DSwitchButton::toggled, q, [q, this](bool ckd) {
+ if (checked == ckd)
+ return;
+
+ checked = ckd;
+ DDciIcon icon = checked ? DDciIcon::fromTheme("switch_on") : DDciIcon::fromTheme("switch_off");
+ player.setIcon(icon);
+ player.play(DDciIcon::Mode::Normal);
+ timer->start();
+
+ Q_EMIT q->checkedChanged(checked);
+ });
+
+ q->connect(&player, &DDciIconPlayer::updated, q, [q]() {
+ q->update();
+ });
+
+ q->connect(timer, &QTimer::timeout, q, [q, this]() {
+ player.stop();
+ player.setIcon(!q->isChecked() ? DDciIcon::fromTheme("switch_on") : DDciIcon::fromTheme("switch_off"));
+ player.setMode(DDciIcon::Normal);
+ timer->stop();
+ });
+
+ q->connect(DGuiApplicationHelper::instance(), &DGuiApplicationHelper::themeTypeChanged, q, initPlayer);
}
DWIDGET_END_NAMESPACE
diff --git a/src/widgets/private/dswitchbutton_p.h b/src/widgets/private/dswitchbutton_p.h
index 6fc76e72e..32f265aaf 100644
--- a/src/widgets/private/dswitchbutton_p.h
+++ b/src/widgets/private/dswitchbutton_p.h
@@ -6,9 +6,11 @@
#define DSWITCHBUTTON_P_H
#include
+#include
#include
+DGUI_USE_NAMESPACE
DWIDGET_BEGIN_NAMESPACE
class DSwitchButtonPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate
@@ -28,6 +30,9 @@ class DSwitchButtonPrivate : public DTK_CORE_NAMESPACE::DObjectPrivate
double animationStartValue = 0.0;
double animationEndValue = 0.0;
+ DDciIconPlayer player;
+ QTimer *timer;
+
public:
D_DECLARE_PUBLIC(DSwitchButton)
};