Qtで Android Switches に相当する要素を使用しようとしています。 QMLでToggleSwitchを見つけましたが、実際のC++ Qtライブラリには何もありません。私は何か不足しているのですか、それともこのウィジェットを自分で再実装する必要がありますか?
@piccyの提案は、以前にそのようなトグルスイッチに対して行ったことです。いくつかの微調整で。
IOSのオン/オフスイッチと同様の動作をエミュレートする必要がありました。つまり、外部アニメーションなしでスライダーを0〜1の制限に設定すると、緩やかな動きが必要になります。
したがって、スライダーの値の範囲をスライダーの最大幅と同じになるように設定しました。
次に、スライダーリリース信号を接続し、値が最大値の半分未満であるかどうかを確認します。そうである場合は、スライダー値を0に設定し、それ以外の場合はスライダー値を最大にします。
これにより、マウスを離したときに優れたドラッグエフェクトと極端なクリップが得られます。
スライダーをドラッグせずに反対側をクリックしたときにトグルするだけの場合は、スライダーの値が変更された信号を接続し、新しい値をチェックしてどちらかの端に近づけ、スライダーの値として設定しますスライダーがそうでない場合)ダウン状態。スライダーが下にある場合は、スライダーの値を変更しないでください。前のドラッグモーションが中断する可能性があります。
次に例を示します。
switch.h
:
#pragma once
#include <QtWidgets>
class Switch : public QAbstractButton {
Q_OBJECT
Q_PROPERTY(int offset READ offset WRITE setOffset)
Q_PROPERTY(QBrush brush READ brush WRITE setBrush)
public:
Switch(QWidget* parent = nullptr);
Switch(const QBrush& brush, QWidget* parent = nullptr);
QSize sizeHint() const override;
QBrush brush() const {
return _brush;
}
void setBrush(const QBrush &brsh) {
_brush = brsh;
}
int offset() const {
return _x;
}
void setOffset(int o) {
_x = o;
update();
}
protected:
void paintEvent(QPaintEvent*) override;
void mouseReleaseEvent(QMouseEvent*) override;
void enterEvent(QEvent*) override;
private:
bool _switch;
qreal _opacity;
int _x, _y, _height, _margin;
QBrush _thumb, _track, _brush;
QPropertyAnimation *_anim = nullptr;
};
switch.cpp
:
Switch::Switch(QWidget *parent) : QAbstractButton(parent),
_height(16),
_opacity(0.000),
_switch(false),
_margin(3),
_thumb("#d5d5d5"),
_anim(new QPropertyAnimation(this, "offset", this))
{
setOffset(_height / 2);
_y = _height / 2;
setBrush(QColor("#009688"));
}
Switch::Switch(const QBrush &brush, QWidget *parent) : QAbstractButton(parent),
_height(16),
_switch(false),
_opacity(0.000),
_margin(3),
_thumb("#d5d5d5"),
_anim(new QPropertyAnimation(this, "offset", this))
{
setOffset(_height / 2);
_y = _height / 2;
setBrush(brush);
}
void Switch::paintEvent(QPaintEvent *e) {
QPainter p(this);
p.setPen(Qt::NoPen);
if (isEnabled()) {
p.setBrush(_switch ? brush() : Qt::black);
p.setOpacity(_switch ? 0.5 : 0.38);
p.setRenderHint(QPainter::Antialiasing, true);
p.drawRoundedRect(QRect(_margin, _margin, width() - 2 * _margin, height() - 2 * _margin), 8.0, 8.0);
p.setBrush(_thumb);
p.setOpacity(1.0);
p.drawEllipse(QRectF(offset() - (_height / 2), _y - (_height / 2), height(), height()));
} else {
p.setBrush(Qt::black);
p.setOpacity(0.12);
p.drawRoundedRect(QRect(_margin, _margin, width() - 2 * _margin, height() - 2 * _margin), 8.0, 8.0);
p.setOpacity(1.0);
p.setBrush(QColor("#BDBDBD"));
p.drawEllipse(QRectF(offset() - (_height / 2), _y - (_height / 2), height(), height()));
}
}
void Switch::mouseReleaseEvent(QMouseEvent *e) {
if (e->button() & Qt::LeftButton) {
_switch = _switch ? false : true;
_thumb = _switch ? _brush : QBrush("#d5d5d5");
if (_switch) {
_anim->setStartValue(_height / 2);
_anim->setEndValue(width() - _height);
_anim->setDuration(120);
_anim->start();
} else {
_anim->setStartValue(offset());
_anim->setEndValue(_height / 2);
_anim->setDuration(120);
_anim->start();
}
}
QAbstractButton::mouseReleaseEvent(e);
}
void Switch::enterEvent(QEvent *e) {
setCursor(Qt::PointingHandCursor);
QAbstractButton::enterEvent(e);
}
QSize Switch::sizeHint() const {
return QSize(2 * (_height + _margin), _height + 2 * _margin);
}
main.cpp
:
#include "switch.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
QWidget *widget = new QWidget;
widget->setWindowFlags(Qt::FramelessWindowHint);
QHBoxLayout layout;
widget->setLayout(&layout);
Switch *_switch = new Switch;
Switch *_switch2 = new Switch;
_switch2->setDisabled(true);
layout.addWidget(_switch);
layout.addWidget(_switch2);
widget->show();
return a.exec();
}
新しいマテリアルスイッチウィジェット!
style.h
/*
* This is nearly complete Material design Switch widget implementation in qtwidgets module.
* More info: https://material.io/design/components/selection-controls.html#switches
* Copyright (C) 2018 Iman Ahmadvand
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* It is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef STYLE_H
#define STYLE_H
#include <QtCore/qeasingcurve.h>
#define cyan500 QColor("#00bcd4")
#define gray50 QColor("#fafafa")
#define black QColor("#000000")
#define gray400 QColor("#bdbdbd")
Q_DECL_IMPORT void qt_blurImage(QPainter *p, QImage &blurImage, qreal radius, bool quality, bool alphaOnly, int transposed = 0); // src/widgets/effects/qpixmapfilter.cpp
namespace Style {
using Type = QEasingCurve::Type;
struct Animation {
Animation() = default;
Animation(Type _easing, int _duration) :easing{ _easing }, duration{ _duration } {
}
Type easing;
int duration;
};
struct Switch {
Switch() :
height{ 36 },
font{ QFont("Roboto medium", 13) },
indicatorMargin{ QMargins(8, 8, 8, 8) },
thumbOnBrush{ cyan500 },
thumbOnOpacity{ 1 },
trackOnBrush{ cyan500 },
trackOnOpacity{ 0.5 },
thumbOffBrush{ gray50 },
thumbOffOpacity{ 1 },
trackOffBrush{ black },
trackOffOpacity{ 0.38 },
thumbDisabled{ gray400 },
thumbDisabledOpacity{ 1 },
trackDisabled{ black },
trackDisabledOpacity{ 0.12 },
textColor{ black },
disabledTextOpacity{ 0.26 },
thumbBrushAnimation{ Animation(Type::Linear, 150) },
trackBrushAnimation{ Animation(Type::Linear, 150) },
thumbPosAniamtion{ Animation(Type::InOutQuad, 150) } {
}
int height;
QFont font;
QMargins indicatorMargin;
QColor thumbOnBrush;
double thumbOnOpacity;
QColor trackOnBrush;
double trackOnOpacity;
QColor thumbOffBrush;
double thumbOffOpacity;
QColor trackOffBrush;
double trackOffOpacity;
QColor thumbDisabled;
double thumbDisabledOpacity;
QColor trackDisabled;
double trackDisabledOpacity;
QColor textColor;
double disabledTextOpacity;
Animation thumbBrushAnimation;
Animation trackBrushAnimation;
Animation thumbPosAniamtion;
};
inline QPixmap drawShadowEllipse(qreal radius, qreal elevation, const QColor& color) {
auto px = QPixmap(radius * 2, radius * 2);
px.fill(Qt::transparent);
{ // draw ellipes
QPainter p(&px);
p.setBrush(color);
p.setPen(Qt::NoPen);
p.setRenderHint(QPainter::Antialiasing, true);
p.drawEllipse(QRectF(0, 0, px.size().width(), px.size().height()).center(), radius - elevation, radius - elevation);
}
QImage tmp(px.size(), QImage::Format_ARGB32_Premultiplied);
tmp.setDevicePixelRatio(px.devicePixelRatioF());
tmp.fill(0);
QPainter tmpPainter(&tmp);
tmpPainter.setCompositionMode(QPainter::CompositionMode_Source);
tmpPainter.drawPixmap(QPointF(), px);
tmpPainter.end();
// blur the alpha channel
QImage blurred(tmp.size(), QImage::Format_ARGB32_Premultiplied);
blurred.setDevicePixelRatio(px.devicePixelRatioF());
blurred.fill(0);
{
QPainter blurPainter(&blurred);
qt_blurImage(&blurPainter, tmp, elevation * 4., true, false);
}
tmp = blurred;
return QPixmap::fromImage(tmp);
}
} // namespace Style
#endif // STYLE_H
switch.h
/*
* This is nearly complete Material design Switch widget implementation in qtwidgets module.
* More info: https://material.io/design/components/selection-controls.html#switches
* Copyright (C) 2018 Iman Ahmadvand
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* It is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef SWITCH_H
#define SWITCH_H
#include <QtWidgets>
#include "style.h"
class Animator : public QVariantAnimation {
Q_OBJECT
Q_PROPERTY(QObject* targetObject READ targetObject WRITE setTargetObject)
public:
explicit Animator(QObject* target, QObject* parent = nullptr);
~Animator();
QObject* targetObject() const;
void setTargetObject(QObject* target);
bool isRunning() const {
return state() == Running;
}
void setup(int duration, QEasingCurve easing = QEasingCurve::Linear);
void interpolate(const QVariant& start, const QVariant& end);
protected:
void updateCurrentValue(const QVariant& value) override;
void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) override;
private:
QPointer<QObject> target;
};
class SelectionControl :public QAbstractButton {
Q_OBJECT
public:
explicit SelectionControl(QWidget* parent = nullptr);
~SelectionControl();
Qt::CheckState checkState() const;
Q_SIGNALS:
void stateChanged(int);
protected:
void enterEvent(QEvent*) override;
void checkStateSet() override;
void nextCheckState() override;
virtual void toggle(Qt::CheckState state) = 0;
};
class Switch :public SelectionControl {
Q_OBJECT
public:
explicit Switch(QWidget* parent = nullptr);
explicit Switch(const QString& text, QWidget* parent = nullptr);
Switch(const QString& text, const QBrush&, QWidget* parent = nullptr);
~Switch();
QSize sizeHint() const override;
protected:
void paintEvent(QPaintEvent *) override;
void resizeEvent(QResizeEvent*) override;
void toggle(Qt::CheckState) override;
void init();
QRect indicatorRect();
QRect textRect();
static inline QColor colorFromOpacity(const QColor& c, qreal opacity) {
return QColor(c.red(), c.green(), c.blue(), opacity * 255.0);
}
static inline bool ltr(QWidget* w) {
if (w)
return w->layoutDirection() == Qt::LeftToRight;
return false;
}
private:
Style::Switch style;
QPixmap shadowPixmap;
QPointer<Animator> thumbBrushAnimation;
QPointer<Animator> trackBrushAnimation;
QPointer<Animator> thumbPosAniamtion;
};
#endif // SWITCH_H
switch.cpp
/*
* This is nearly complete Material design Switch widget implementation in qtwidgets module.
* More info: https://material.io/design/components/selection-controls.html#switches
* Copyright (C) 2018 Iman Ahmadvand
*
* This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* It is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "switch.h"
#define CORNER_RADIUS 8.0
#define THUMB_RADIUS 14.5
#define SHADOW_ELEVATION 2.0
Animator::Animator(QObject* target, QObject* parent) : QVariantAnimation(parent) {
setTargetObject(target);
}
Animator::~Animator() {
stop();
}
QObject* Animator::targetObject() const {
return target.data();
}
void Animator::setTargetObject(QObject *_target) {
if (target.data() == _target)
return;
if (isRunning()) {
qWarning("Animation::setTargetObject: you can't change the target of a running animation");
return;
}
target = _target;
}
void Animator::updateCurrentValue(const QVariant& value) {
Q_UNUSED(value);
if (!target.isNull()) {
auto update = QEvent(QEvent::StyleAnimationUpdate);
update.setAccepted(false);
QCoreApplication::sendEvent(target.data(), &update);
if (!update.isAccepted())
stop();
}
}
void Animator::updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) {
if (target.isNull() && oldState == Stopped) {
qWarning("Animation::updateState: Changing state of an animation without target");
return;
}
QVariantAnimation::updateState(newState, oldState);
if (!endValue().isValid() && direction() == Forward) {
qWarning("Animation::updateState (%s): starting an animation without end value", targetObject()->metaObject()->className());
}
}
void Animator::setup(int duration, QEasingCurve easing) {
setDuration(duration);
setEasingCurve(easing);
}
void Animator::interpolate(const QVariant& _start, const QVariant& end) {
setStartValue(_start);
setEndValue(end);
start();
}
SelectionControl::SelectionControl(QWidget * parent) :QAbstractButton(parent) {
setObjectName("SelectionControl");
setCheckable(true);
}
SelectionControl::~SelectionControl() {
}
void SelectionControl::enterEvent(QEvent* e) {
setCursor(Qt::PointingHandCursor);
QAbstractButton::enterEvent(e);
}
Qt::CheckState SelectionControl::checkState() const {
return isChecked() ? Qt::Checked : Qt::Unchecked;
}
void SelectionControl::checkStateSet() {
const auto state = checkState();
emit stateChanged(state);
toggle(state);
}
void SelectionControl::nextCheckState() {
QAbstractButton::nextCheckState();
SelectionControl::checkStateSet();
}
void Switch::init() {
setFont(style.font);
setObjectName("Switch");
/* setup animations */
thumbBrushAnimation = new Animator{ this, this };
trackBrushAnimation = new Animator{ this, this };
thumbPosAniamtion = new Animator{ this, this };
thumbPosAniamtion->setup(style.thumbPosAniamtion.duration, style.thumbPosAniamtion.easing);
trackBrushAnimation->setup(style.trackBrushAnimation.duration, style.trackBrushAnimation.easing);
thumbBrushAnimation->setup(style.thumbBrushAnimation.duration, style.thumbBrushAnimation.easing);
/* set init values */
trackBrushAnimation->setStartValue(colorFromOpacity(style.trackOffBrush, style.trackOffOpacity));
trackBrushAnimation->setEndValue(colorFromOpacity(style.trackOffBrush, style.trackOffOpacity));
thumbBrushAnimation->setStartValue(colorFromOpacity(style.thumbOffBrush, style.thumbOffOpacity));
thumbBrushAnimation->setEndValue(colorFromOpacity(style.thumbOffBrush, style.thumbOffOpacity));
/* set standard palettes */
auto p = palette();
p.setColor(QPalette::Active, QPalette::ButtonText, style.textColor);
p.setColor(QPalette::Disabled, QPalette::ButtonText, style.textColor);
setPalette(p);
setSizePolicy(QSizePolicy(QSizePolicy::Policy::Preferred, QSizePolicy::Policy::Fixed));
}
QRect Switch::indicatorRect() {
const auto w = style.indicatorMargin.left() + style.height + style.indicatorMargin.right();
return ltr(this) ? QRect(0, 0, w, style.height) : QRect(width() - w, 0, w, style.height);
}
QRect Switch::textRect() {
const auto w = style.indicatorMargin.left() + style.height + style.indicatorMargin.right();
return ltr(this) ? rect().marginsRemoved(QMargins(w, 0, 0, 0)) : rect().marginsRemoved(QMargins(0, 0, w, 0));
}
Switch::Switch(QWidget* parent) : SelectionControl(parent) {
init();
}
Switch::Switch(const QString& text, QWidget* parent) : Switch(parent) {
setText(text);
}
Switch::Switch(const QString& text, const QBrush& brush, QWidget* parent) : Switch(text, parent) {
style.thumbOnBrush = brush.color();
style.trackOnBrush = brush.color();
}
Switch::~Switch() {
}
QSize Switch::sizeHint() const {
auto h = style.height;
auto w = style.indicatorMargin.left() + style.height + style.indicatorMargin.right() + fontMetrics().width(text());
return QSize(w, h);
}
void Switch::paintEvent(QPaintEvent *) {
/* for desktop usage we do not need Radial reaction */
QPainter p(this);
const auto _indicatorRect = indicatorRect();
const auto _textRect = textRect();
auto trackMargin = style.indicatorMargin;
trackMargin.setTop(trackMargin.top() + 2);
trackMargin.setBottom(trackMargin.bottom() + 2);
QRectF trackRect = _indicatorRect.marginsRemoved(trackMargin);
if (isEnabled()) {
p.setOpacity(1.0);
p.setPen(Qt::NoPen);
/* draw track */
p.setBrush(trackBrushAnimation->currentValue().value<QColor>());
p.setRenderHint(QPainter::Antialiasing, true);
p.drawRoundedRect(trackRect, CORNER_RADIUS, CORNER_RADIUS);
p.setRenderHint(QPainter::Antialiasing, false);
/* draw thumb */
trackRect.setX(trackRect.x() - trackMargin.left() - trackMargin.right() - 2 + thumbPosAniamtion->currentValue().toInt());
auto thumbRect = trackRect;
if (!shadowPixmap.isNull())
p.drawPixmap(thumbRect.center() - QPointF(THUMB_RADIUS, THUMB_RADIUS - 1.0), shadowPixmap);
p.setBrush(thumbBrushAnimation->currentValue().value<QColor>());
p.setRenderHint(QPainter::Antialiasing, true);
p.drawEllipse(thumbRect.center(), THUMB_RADIUS - SHADOW_ELEVATION - 1.0, THUMB_RADIUS - SHADOW_ELEVATION - 1.0);
p.setRenderHint(QPainter::Antialiasing, false);
/* draw text */
if (text().isEmpty())
return;
p.setOpacity(1.0);
p.setPen(palette().color(QPalette::Active, QPalette::ButtonText));
p.setFont(font());
p.drawText(_textRect, Qt::AlignLeft | Qt::AlignVCenter, text());
} else {
p.setOpacity(style.trackDisabledOpacity);
p.setPen(Qt::NoPen);
// draw track
p.setBrush(style.trackDisabled);
p.setRenderHint(QPainter::Antialiasing, true);
p.drawRoundedRect(trackRect, CORNER_RADIUS, CORNER_RADIUS);
p.setRenderHint(QPainter::Antialiasing, false);
// draw thumb
p.setOpacity(1.0);
if (!isChecked())
trackRect.setX(trackRect.x() - trackMargin.left() - trackMargin.right() - 2);
else
trackRect.setX(trackRect.x() + trackMargin.left() + trackMargin.right() + 2);
auto thumbRect = trackRect;
if (!shadowPixmap.isNull())
p.drawPixmap(thumbRect.center() - QPointF(THUMB_RADIUS, THUMB_RADIUS - 1.0), shadowPixmap);
p.setOpacity(1.0);
p.setBrush(style.thumbDisabled);
p.setRenderHint(QPainter::Antialiasing, true);
p.drawEllipse(thumbRect.center(), THUMB_RADIUS - SHADOW_ELEVATION - 1.0, THUMB_RADIUS - SHADOW_ELEVATION - 1.0);
if (text().isEmpty())
return;
p.setOpacity(style.disabledTextOpacity);
p.setPen(palette().color(QPalette::Disabled, QPalette::ButtonText));
p.setFont(font());
p.drawText(_textRect, Qt::AlignLeft | Qt::AlignVCenter, text());
}
}
void Switch::resizeEvent(QResizeEvent* e) {
shadowPixmap = Style::drawShadowEllipse(THUMB_RADIUS, SHADOW_ELEVATION, QColor(0, 0, 0, 70));
SelectionControl::resizeEvent(e);
}
void Switch::toggle(Qt::CheckState state) {
if (state == Qt::Checked) {
thumbPosAniamtion->interpolate(0, (style.indicatorMargin.left() + style.indicatorMargin.right() + 2) * 2);
thumbBrushAnimation->interpolate(colorFromOpacity(style.thumbOffBrush, style.thumbOffOpacity), colorFromOpacity(style.thumbOnBrush, style.thumbOnOpacity));
trackBrushAnimation->interpolate(colorFromOpacity(style.trackOffBrush, style.trackOffOpacity), colorFromOpacity(style.trackOnBrush, style.trackOnOpacity));
} else { // Qt::Unchecked
thumbPosAniamtion->interpolate(thumbPosAniamtion->currentValue().toInt(), 0);
thumbBrushAnimation->interpolate(colorFromOpacity(style.thumbOnBrush, style.thumbOnOpacity), colorFromOpacity(style.thumbOffBrush, style.thumbOffOpacity));
trackBrushAnimation->interpolate(colorFromOpacity(style.trackOnBrush, style.trackOnOpacity), colorFromOpacity(style.trackOffBrush, style.trackOffOpacity));
}
}
main.cpp
#include "switch.h"
int main(int argc, char *argv[]) {
QApplication application(argc, argv);
QWidget container;
QVBoxLayout mainLayout;
container.setLayout(&mainLayout);
Switch* switch1 = new Switch("SWITCH");
mainLayout.addWidget(switch1);
Switch* switch2 = new Switch("SWITCH");
mainLayout.addWidget(switch2);
switch2->setDisabled(true);
Switch* switch3 = new Switch("SWITCH");
mainLayout.addWidget(switch3);
switch3->setLayoutDirection(Qt::RightToLeft);
Switch* switch4 = new Switch("SWITCH");
mainLayout.addWidget(switch4);
switch4->setLayoutDirection(Qt::RightToLeft);
switch4->setChecked(true);
switch4->setDisabled(true);
QButtonGroup bg;
Switch* item1 = new Switch("ITEM1");
Switch* item2 = new Switch("ITEM2");
bg.addButton(item1);
bg.addButton(item2);
mainLayout.addWidget(item1);
mainLayout.addWidget(item2);
mainLayout.setMargin(100);
container.show();
return application.exec();
}
結果:
数か月前に、一般的なデスクトップスタイル(C++とPython利用可能なバージョン; Pythonバージョンがプロトタイプでした、つまり、動作が異なる可能性があります。paintEvent
を使用して美学が完全にカスタマイズされていることに注意してください。システムに応じて異なるビジュアルを期待しないでください。
C++の実装
注:インクルード(私の例にはありません)を忘れないでください。
用途:
SwitchButton* sbtn = new SwitchButton(this); // Default style is Style::ONOFF
bool current = sbtn->value();
sbtn->setValue(!current);
(...)。hpp
class SwitchButton : public QWidget
{
Q_OBJECT
Q_DISABLE_COPY(SwitchButton)
public:
enum Style
{
YESNO,
ONOFF,
BOOL,
EMPTY
};
public:
explicit SwitchButton(QWidget* parent = nullptr, Style style = Style::ONOFF);
~SwitchButton() override;
//-- QWidget methods
void mousePressEvent(QMouseEvent *) override;
void paintEvent(QPaintEvent* event) override;
void setEnabled(bool);
//-- Setters
void setDuration(int);
void setValue(bool);
//-- Getters
bool value() const;
signals:
void valueChanged(bool newvalue);
private:
class SwitchCircle;
class SwitchBackground;
void _update();
private:
bool _value;
int _duration;
QLinearGradient _lg;
QLinearGradient _lg2;
QLinearGradient _lg_disabled;
QColor _pencolor;
QColor _offcolor;
QColor _oncolor;
int _tol;
int _borderradius;
// This order for definition is important (these widgets overlap)
QLabel* _labeloff;
SwitchBackground* _background;
QLabel* _labelon;
SwitchCircle* _circle;
bool _enabled;
QPropertyAnimation* __btn_move;
QPropertyAnimation* __back_move;
};
class SwitchButton::SwitchBackground : public QWidget
{
Q_OBJECT
Q_DISABLE_COPY(SwitchBackground)
public:
explicit SwitchBackground(QWidget* parent = nullptr, QColor color = QColor(154, 205, 50), bool rect = false);
~SwitchBackground() override;
//-- QWidget methods
void paintEvent(QPaintEvent* event) override;
void setEnabled(bool);
private:
bool _rect;
int _borderradius;
QColor _color;
QColor _pencolor;
QLinearGradient _lg;
QLinearGradient _lg_disabled;
bool _enabled;
};
class SwitchButton::SwitchCircle : public QWidget
{
Q_OBJECT
Q_DISABLE_COPY(SwitchCircle)
public:
explicit SwitchCircle(QWidget* parent = nullptr, QColor color = QColor(255, 255, 255), bool rect = false);
~SwitchCircle() override;
//-- QWidget methods
void paintEvent(QPaintEvent* event) override;
void setEnabled(bool);
private:
bool _rect;
int _borderradius;
QColor _color;
QColor _pencolor;
QRadialGradient _rg;
QLinearGradient _lg;
QLinearGradient _lg_disabled;
bool _enabled;
};
(...)。cpp
SwitchButton::SwitchButton(QWidget* parent, Style style)
: QWidget(parent)
, _value(false)
, _duration(100)
, _enabled(true)
{
_pencolor = QColor(120, 120, 120);
_lg = QLinearGradient(35, 30, 35, 0);
_lg.setColorAt(0, QColor(210, 210, 210));
_lg.setColorAt(0.25, QColor(255, 255, 255));
_lg.setColorAt(0.82, QColor(255, 255, 255));
_lg.setColorAt(1, QColor(210, 210, 210));
_lg2 = QLinearGradient(50, 30, 35, 0);
_lg2.setColorAt(0, QColor(230, 230, 230));
_lg2.setColorAt(0.25, QColor(255, 255, 255));
_lg2.setColorAt(0.82, QColor(255, 255, 255));
_lg2.setColorAt(1, QColor(230, 230, 230));
_lg_disabled = QLinearGradient(50, 30, 35, 0);
_lg_disabled.setColorAt(0, QColor(200, 200, 200));
_lg_disabled.setColorAt(0.25, QColor(230, 230, 230));
_lg_disabled.setColorAt(0.82, QColor(230, 230, 230));
_lg_disabled.setColorAt(1, QColor(200, 200, 200));
_offcolor = QColor(255, 255, 255);
_oncolor = QColor(154, 205, 50);
_tol = 0;
_borderradius = 12;
_labeloff = NEW QLabel(this);
_background = NEW SwitchBackground(this, _oncolor);
_labelon = NEW QLabel(this);
_circle = NEW SwitchCircle(this, _offcolor);
__btn_move = NEW QPropertyAnimation(this);
__back_move = NEW QPropertyAnimation(this);
__btn_move->setTargetObject(_circle);
__btn_move->setPropertyName("pos");
__back_move->setTargetObject(_background);
__back_move->setPropertyName("size");
setWindowFlags(Qt::FramelessWindowHint);
setAttribute(Qt::WA_TranslucentBackground);
_labeloff->setText("Off");
_labelon->setText("On");
_labeloff->move(31, 5);
_labelon->move(15, 5);
setFixedSize(QSize(60, 24));
if (style == Style::YESNO)
{
_labeloff->setText("No");
_labelon->setText("Yes");
_labeloff->move(33, 5);
_labelon->move(12, 5);
setFixedSize(QSize(60, 24));
}
else if (style == Style::BOOL)
{
_labeloff->setText("False");
_labelon->setText("True");
_labeloff->move(37, 5);
_labelon->move(12, 5);
setFixedSize(QSize(75, 24));
}
if (style == Style::EMPTY)
{
_labeloff->setText("");
_labelon->setText("");
_labeloff->move(31, 5);
_labelon->move(12, 5);
setFixedSize(QSize(45, 24));
}
_labeloff->setStyleSheet("color: rgb(120, 120, 120); font-weight: bold;");
_labelon->setStyleSheet("color: rgb(255, 255, 255); font-weight: bold;");
_background->resize(20, 20);
_background->move(2, 2);
_circle->move(2, 2);
}
SwitchButton::~SwitchButton()
{
delete _circle;
delete _background;
delete _labeloff;
delete _labelon;
delete __btn_move;
delete __back_move;
}
void SwitchButton::paintEvent(QPaintEvent*)
{
QPainter* Painter = new QPainter;
Painter->begin(this);
Painter->setRenderHint(QPainter::Antialiasing, true);
QPen pen(Qt::NoPen);
Painter->setPen(pen);
Painter->setBrush(_pencolor);
Painter->drawRoundedRect(0, 0
, width(), height()
, 12, 12);
Painter->setBrush(_lg);
Painter->drawRoundedRect(1, 1
, width() - 2, height() - 2
, 10, 10);
Painter->setBrush(QColor(210, 210, 210));
Painter->drawRoundedRect(2, 2
, width() - 4, height() - 4
, 10, 10);
if (_enabled)
{
Painter->setBrush(_lg2);
Painter->drawRoundedRect(3, 3
, width() - 6, height() - 6
, 7, 7);
}
else
{
Painter->setBrush(_lg_disabled);
Painter->drawRoundedRect(3, 3
, width() - 6, height() - 6
, 7, 7);
}
Painter->end();
}
void SwitchButton::mousePressEvent(QMouseEvent*)
{
if (!_enabled)
return;
__btn_move->stop();
__back_move->stop();
__btn_move->setDuration(_duration);
__back_move->setDuration(_duration);
int hback = 20;
QSize initial_size(hback, hback);
QSize final_size(width() - 4, hback);
int xi = 2;
int y = 2;
int xf = width() - 22;
if (_value)
{
final_size = QSize(hback, hback);
initial_size = QSize(width() - 4, hback);
xi = xf;
xf = 2;
}
__btn_move->setStartValue(QPoint(xi, y));
__btn_move->setEndValue(QPoint(xf, y));
__back_move->setStartValue(initial_size);
__back_move->setEndValue(final_size);
__btn_move->start();
__back_move->start();
// Assigning new current value
_value = !_value;
emit valueChanged(_value);
}
void SwitchButton::setEnabled(bool flag)
{
_enabled = flag;
_circle->setEnabled(flag);
_background->setEnabled(flag);
if (flag)
_labelon->show();
else
{
if (value())
_labelon->show();
else
_labelon->hide();
}
QWidget::setEnabled(flag);
}
void SwitchButton::setDuration(int time)
{
_duration = time;
}
void SwitchButton::setValue(bool flag)
{
if (flag == value())
return;
else
{
_value = flag;
_update();
setEnabled(_enabled);
}
}
bool SwitchButton::value() const
{
return _value;
}
void SwitchButton::_update()
{
int hback = 20;
QSize final_size(width() - 4, hback);
int y = 2;
int xf = width() - 22;
if (_value)
{
final_size = QSize(hback, hback);
xf = 2;
}
_circle->move(QPoint(xf, y));
_background->resize(final_size);
}
SwitchButton::SwitchBackground::SwitchBackground(QWidget* parent, QColor color, bool rect)
: QWidget(parent)
, _rect(rect)
, _borderradius(12)
, _color(color)
, _pencolor(QColor(170, 170, 170))
{
setFixedHeight(20);
_lg = QLinearGradient(0, 25, 70, 0);
_lg.setColorAt(0, QColor(154, 194, 50));
_lg.setColorAt(0.25, QColor(154, 210, 50));
_lg.setColorAt(0.95, QColor(154, 194, 50));
_lg_disabled = QLinearGradient(0, 25, 70, 0);
_lg_disabled.setColorAt(0, QColor(190, 190, 190));
_lg_disabled.setColorAt(0.25, QColor(230, 230, 230));
_lg_disabled.setColorAt(0.95, QColor(190, 190, 190));
if (_rect)
_borderradius = 0;
_enabled = true;
}
SwitchButton::SwitchBackground::~SwitchBackground()
{
}
void SwitchButton::SwitchBackground::paintEvent(QPaintEvent*)
{
QPainter* Painter = new QPainter;
Painter->begin(this);
Painter->setRenderHint(QPainter::Antialiasing, true);
QPen pen(Qt::NoPen);
Painter->setPen(pen);
if (_enabled)
{
Painter->setBrush(QColor(154, 190, 50));
Painter->drawRoundedRect(0, 0
, width(), height()
, 10, 10);
Painter->setBrush(_lg);
Painter->drawRoundedRect(1, 1, width()-2, height()-2, 8, 8);
}
else
{
Painter->setBrush(QColor(150, 150, 150));
Painter->drawRoundedRect(0, 0
, width(), height()
, 10, 10);
Painter->setBrush(_lg_disabled);
Painter->drawRoundedRect(1, 1, width() - 2, height() - 2, 8, 8);
}
Painter->end();
}
void SwitchButton::SwitchBackground::setEnabled(bool flag)
{
_enabled = flag;
}
SwitchButton::SwitchCircle::SwitchCircle(QWidget* parent, QColor color, bool rect)
: QWidget(parent)
, _rect(rect)
, _borderradius(12)
, _color(color)
, _pencolor(QColor(120, 120, 120))
{
setFixedSize(20, 20);
_rg = QRadialGradient(static_cast<int>(width() / 2), static_cast<int>(height() / 2), 12);
_rg.setColorAt(0, QColor(255, 255, 255));
_rg.setColorAt(0.6, QColor(255, 255, 255));
_rg.setColorAt(1, QColor(205, 205, 205));
_lg = QLinearGradient(3, 18, 20, 4);
_lg.setColorAt(0, QColor(255, 255, 255));
_lg.setColorAt(0.55, QColor(230, 230, 230));
_lg.setColorAt(0.72, QColor(255, 255, 255));
_lg.setColorAt(1, QColor(255, 255, 255));
_lg_disabled = QLinearGradient(3, 18, 20, 4);
_lg_disabled.setColorAt(0, QColor(230, 230, 230));
_lg_disabled.setColorAt(0.55, QColor(210, 210, 210));
_lg_disabled.setColorAt(0.72, QColor(230, 230, 230));
_lg_disabled.setColorAt(1, QColor(230, 230, 230));
_enabled = true;
}
SwitchButton::SwitchCircle::~SwitchCircle()
{
}
void SwitchButton::SwitchCircle::paintEvent(QPaintEvent*)
{
QPainter* Painter = new QPainter;
Painter->begin(this);
Painter->setRenderHint(QPainter::Antialiasing, true);
QPen pen(Qt::NoPen);
Painter->setPen(pen);
Painter->setBrush(_pencolor);
Painter->drawEllipse(0, 0, 20, 20);
Painter->setBrush(_rg);
Painter->drawEllipse(1, 1, 18, 18);
Painter->setBrush(QColor(210, 210, 210));
Painter->drawEllipse(2, 2, 16, 16);
if (_enabled)
{
Painter->setBrush(_lg);
Painter->drawEllipse(3, 3, 14, 14);
}
else
{
Painter->setBrush(_lg_disabled);
Painter->drawEllipse(3, 3, 14, 14);
}
Painter->end();
}
void SwitchButton::SwitchCircle::setEnabled(bool flag)
{
_enabled = flag;
}
Python実装(プロトタイプ; PyQt5)
用途:
switchbtn = SwitchButton(self, "On", 15, "Off", 31, 60)
(...)。py
from PyQt5 import QtWidgets, QtCore, QtGui
class SwitchButton(QtWidgets.QWidget):
def __init__(self, parent=None, w1="Yes", l1=12, w2="No", l2=33, width=60):
super(SwitchButton, self).__init__(parent)
self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
self.setAttribute(QtCore.Qt.WA_TranslucentBackground)
self.__labeloff = QtWidgets.QLabel(self)
self.__labeloff.setText(w2)
self.__labeloff.setStyleSheet("""color: rgb(120, 120, 120); font-weight: bold;""")
self.__background = Background(self)
self.__labelon = QtWidgets.QLabel(self)
self.__labelon.setText(w1)
self.__labelon.setStyleSheet("""color: rgb(255, 255, 255); font-weight: bold;""")
self.__circle = Circle(self)
self.__circlemove = None
self.__ellipsemove = None
self.__enabled = True
self.__duration = 100
self.__value = False
self.setFixedSize(width, 24)
self.__background.resize(20, 20)
self.__background.move(2, 2)
self.__circle.move(2, 2)
self.__labelon.move(l1, 5)
self.__labeloff.move(l2, 5)
def setDuration(self, time):
self.__duration = time
def mousePressEvent(self, event):
if not self.__enabled:
return
self.__circlemove = QtCore.QPropertyAnimation(self.__circle, b"pos")
self.__circlemove.setDuration(self.__duration)
self.__ellipsemove = QtCore.QPropertyAnimation(self.__background, b"size")
self.__ellipsemove.setDuration(self.__duration)
xs = 2
y = 2
xf = self.width()-22
hback = 20
isize = QtCore.QSize(hback, hback)
bsize = QtCore.QSize(self.width()-4, hback)
if self.__value:
xf = 2
xs = self.width()-22
bsize = QtCore.QSize(hback, hback)
isize = QtCore.QSize(self.width()-4, hback)
self.__circlemove.setStartValue(QtCore.QPoint(xs, y))
self.__circlemove.setEndValue(QtCore.QPoint(xf, y))
self.__ellipsemove.setStartValue(isize)
self.__ellipsemove.setEndValue(bsize)
self.__circlemove.start()
self.__ellipsemove.start()
self.__value = not self.__value
def paintEvent(self, event):
s = self.size()
qp = QtGui.QPainter()
qp.begin(self)
qp.setRenderHint(QtGui.QPainter.Antialiasing, True)
pen = QtGui.QPen(QtCore.Qt.NoPen)
qp.setPen(pen)
qp.setBrush(QtGui.QColor(120, 120, 120))
qp.drawRoundedRect(0, 0, s.width(), s.height(), 12, 12)
lg = QtGui.QLinearGradient(35, 30, 35, 0)
lg.setColorAt(0, QtGui.QColor(210, 210, 210, 255))
lg.setColorAt(0.25, QtGui.QColor(255, 255, 255, 255))
lg.setColorAt(0.82, QtGui.QColor(255, 255, 255, 255))
lg.setColorAt(1, QtGui.QColor(210, 210, 210, 255))
qp.setBrush(lg)
qp.drawRoundedRect(1, 1, s.width()-2, s.height()-2, 10, 10)
qp.setBrush(QtGui.QColor(210, 210, 210))
qp.drawRoundedRect(2, 2, s.width() - 4, s.height() - 4, 10, 10)
if self.__enabled:
lg = QtGui.QLinearGradient(50, 30, 35, 0)
lg.setColorAt(0, QtGui.QColor(230, 230, 230, 255))
lg.setColorAt(0.25, QtGui.QColor(255, 255, 255, 255))
lg.setColorAt(0.82, QtGui.QColor(255, 255, 255, 255))
lg.setColorAt(1, QtGui.QColor(230, 230, 230, 255))
qp.setBrush(lg)
qp.drawRoundedRect(3, 3, s.width() - 6, s.height() - 6, 7, 7)
else:
lg = QtGui.QLinearGradient(50, 30, 35, 0)
lg.setColorAt(0, QtGui.QColor(200, 200, 200, 255))
lg.setColorAt(0.25, QtGui.QColor(230, 230, 230, 255))
lg.setColorAt(0.82, QtGui.QColor(230, 230, 230, 255))
lg.setColorAt(1, QtGui.QColor(200, 200, 200, 255))
qp.setBrush(lg)
qp.drawRoundedRect(3, 3, s.width() - 6, s.height() - 6, 7, 7)
qp.end()
class Circle(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Circle, self).__init__(parent)
self.__enabled = True
self.setFixedSize(20, 20)
def paintEvent(self, event):
s = self.size()
qp = QtGui.QPainter()
qp.begin(self)
qp.setRenderHint(QtGui.QPainter.Antialiasing, True)
qp.setPen(QtCore.Qt.NoPen)
qp.setBrush(QtGui.QColor(120, 120, 120))
qp.drawEllipse(0, 0, 20, 20)
rg = QtGui.QRadialGradient(int(self.width() / 2), int(self.height() / 2), 12)
rg.setColorAt(0, QtGui.QColor(255, 255, 255))
rg.setColorAt(0.6, QtGui.QColor(255, 255, 255))
rg.setColorAt(1, QtGui.QColor(205, 205, 205))
qp.setBrush(QtGui.QBrush(rg))
qp.drawEllipse(1,1, 18, 18)
qp.setBrush(QtGui.QColor(210, 210, 210))
qp.drawEllipse(2, 2, 16, 16)
if self.__enabled:
lg = QtGui.QLinearGradient(3, 18,20, 4)
lg.setColorAt(0, QtGui.QColor(255, 255, 255, 255))
lg.setColorAt(0.55, QtGui.QColor(230, 230, 230, 255))
lg.setColorAt(0.72, QtGui.QColor(255, 255, 255, 255))
lg.setColorAt(1, QtGui.QColor(255, 255, 255, 255))
qp.setBrush(lg)
qp.drawEllipse(3,3, 14, 14)
else:
lg = QtGui.QLinearGradient(3, 18, 20, 4)
lg.setColorAt(0, QtGui.QColor(230, 230, 230))
lg.setColorAt(0.55, QtGui.QColor(210, 210, 210))
lg.setColorAt(0.72, QtGui.QColor(230, 230, 230))
lg.setColorAt(1, QtGui.QColor(230, 230, 230))
qp.setBrush(lg)
qp.drawEllipse(3, 3, 14, 14)
qp.end()
class Background(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Background, self).__init__(parent)
self.__enabled = True
self.setFixedHeight(20)
def paintEvent(self, event):
s = self.size()
qp = QtGui.QPainter()
qp.begin(self)
qp.setRenderHint(QtGui.QPainter.Antialiasing, True)
pen = QtGui.QPen(QtCore.Qt.NoPen)
qp.setPen(pen)
qp.setBrush(QtGui.QColor(154,205,50))
if self.__enabled:
qp.setBrush(QtGui.QColor(154, 190, 50))
qp.drawRoundedRect(0, 0, s.width(), s.height(), 10, 10)
lg = QtGui.QLinearGradient(0, 25, 70, 0)
lg.setColorAt(0, QtGui.QColor(154, 184, 50))
lg.setColorAt(0.35, QtGui.QColor(154, 210, 50))
lg.setColorAt(0.85, QtGui.QColor(154, 184, 50))
qp.setBrush(lg)
qp.drawRoundedRect(1, 1, s.width() - 2, s.height() - 2, 8, 8)
else:
qp.setBrush(QtGui.QColor(150, 150, 150))
qp.drawRoundedRect(0, 0, s.width(), s.height(), 10, 10)
lg = QtGui.QLinearGradient(5, 25, 60, 0)
lg.setColorAt(0, QtGui.QColor(190, 190, 190))
lg.setColorAt(0.35, QtGui.QColor(230, 230, 230))
lg.setColorAt(0.85, QtGui.QColor(190, 190, 190))
qp.setBrush(lg)
qp.drawRoundedRect(1, 1, s.width() - 2, s.height() - 2, 8, 8)
qp.end()
これはPython 3/@ IMAN4KのPyQt5実装 answer です。
元の実装に対する改善:
from PyQt5.QtCore import QPropertyAnimation, QRectF, QSize, Qt, pyqtProperty
from PyQt5.QtGui import QPainter
from PyQt5.QtWidgets import (
QAbstractButton,
QApplication,
QHBoxLayout,
QSizePolicy,
QWidget,
)
class Switch(QAbstractButton):
def __init__(self, parent=None, track_radius=10, thumb_radius=8):
super().__init__(parent=parent)
self.setCheckable(True)
self.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
self._track_radius = track_radius
self._thumb_radius = thumb_radius
self._margin = max(0, self._thumb_radius - self._track_radius)
self._base_offset = max(self._thumb_radius, self._track_radius)
self._end_offset = {
True: lambda: self.width() - self._base_offset,
False: lambda: self._base_offset,
}
self._offset = self._base_offset
palette = self.palette()
if self._thumb_radius > self._track_radius:
self._track_color = {
True: palette.highlight(),
False: palette.dark(),
}
self._thumb_color = {
True: palette.highlight(),
False: palette.light(),
}
self._text_color = {
True: palette.highlightedText().color(),
False: palette.dark().color(),
}
self._thumb_text = {
True: '',
False: '',
}
self._track_opacity = 0.5
else:
self._thumb_color = {
True: palette.highlightedText(),
False: palette.light(),
}
self._track_color = {
True: palette.highlight(),
False: palette.dark(),
}
self._text_color = {
True: palette.highlight().color(),
False: palette.dark().color(),
}
self._thumb_text = {
True: '✔',
False: '✕',
}
self._track_opacity = 1
@pyqtProperty(int)
def offset(self):
return self._offset
@offset.setter
def offset(self, value):
self._offset = value
self.update()
def sizeHint(self): # pylint: disable=invalid-name
return QSize(
4 * self._track_radius + 2 * self._margin,
2 * self._track_radius + 2 * self._margin,
)
def setChecked(self, checked):
super().setChecked(checked)
self.offset = self._end_offset[checked]()
def resizeEvent(self, event):
super().resizeEvent(event)
self.offset = self._end_offset[self.isChecked()]()
def paintEvent(self, event): # pylint: disable=invalid-name, unused-argument
p = QPainter(self)
p.setRenderHint(QPainter.Antialiasing, True)
p.setPen(Qt.NoPen)
track_opacity = self._track_opacity
thumb_opacity = 1.0
text_opacity = 1.0
if self.isEnabled():
track_brush = self._track_color[self.isChecked()]
thumb_brush = self._thumb_color[self.isChecked()]
text_color = self._text_color[self.isChecked()]
else:
track_opacity *= 0.8
track_brush = self.palette().shadow()
thumb_brush = self.palette().mid()
text_color = self.palette().shadow().color()
p.setBrush(track_brush)
p.setOpacity(track_opacity)
p.drawRoundedRect(
self._margin,
self._margin,
self.width() - 2 * self._margin,
self.height() - 2 * self._margin,
self._track_radius,
self._track_radius,
)
p.setBrush(thumb_brush)
p.setOpacity(thumb_opacity)
p.drawEllipse(
self.offset - self._thumb_radius,
self._base_offset - self._thumb_radius,
2 * self._thumb_radius,
2 * self._thumb_radius,
)
p.setPen(text_color)
p.setOpacity(text_opacity)
font = p.font()
font.setPixelSize(1.5 * self._thumb_radius)
p.setFont(font)
p.drawText(
QRectF(
self.offset - self._thumb_radius,
self._base_offset - self._thumb_radius,
2 * self._thumb_radius,
2 * self._thumb_radius,
),
Qt.AlignCenter,
self._thumb_text[self.isChecked()],
)
def mouseReleaseEvent(self, event): # pylint: disable=invalid-name
super().mouseReleaseEvent(event)
if event.button() == Qt.LeftButton:
anim = QPropertyAnimation(self, b'offset', self)
anim.setDuration(120)
anim.setStartValue(self.offset)
anim.setEndValue(self._end_offset[self.isChecked()]())
anim.start()
def enterEvent(self, event): # pylint: disable=invalid-name
self.setCursor(Qt.PointingHandCursor)
super().enterEvent(event)
def main():
app = QApplication([])
# Thumb size < track size (Gitlab style)
s1 = Switch()
s1.toggled.connect(lambda c: print('toggled', c))
s1.clicked.connect(lambda c: print('clicked', c))
s1.pressed.connect(lambda: print('pressed'))
s1.released.connect(lambda: print('released'))
s2 = Switch()
s2.setEnabled(False)
# Thumb size > track size (Android style)
s3 = Switch(thumb_radius=11, track_radius=8)
s4 = Switch(thumb_radius=11, track_radius=8)
s4.setEnabled(False)
l = QHBoxLayout()
l.addWidget(s1)
l.addWidget(s2)
l.addWidget(s3)
l.addWidget(s4)
w = QWidget()
w.setLayout(l)
w.show()
app.exec()
if __name__ == '__main__':
main()
0から1の範囲の水平方向のQSliderコントロールを使用してこれを行うこともできます。ダイアログの幅を超えないように、最大幅を50程度に設定することをお勧めします。 。次に、スタイルシートで微調整して外観を改善したり、サブクラス化してコントロールを自分で描画したりできます。見栄えを良くするためにコードを多く取りすぎないかもしれません。
まあ、あなたは QCheckBox を使わなければならないでしょう。これはトグルスイッチではありませんが、同じことを行います。本当に異なるビジュアルが必要な場合は、カスタムウィジェットを作成する必要があります
ダビタは正しい 彼の答えでは チェックボックスに関するところ。ただし、3番目の例(オン/オフスイッチ)に似たものを探している場合は、2つの QPushButton sを使用して、それらを checkable に設定します。それらを autoexclusive と同時に作成すれば、問題はありません。
少し視覚的なスタイリング スタイルシートを使用 で、スポットにならなくても近づくことができるはずです。
QRadioButton および QPushButton とともに checkable も参照してください。一部のスタイルシートまたはカスタム描画は、「オン/オフスイッチの切り替え」のように作成できます。
私はこのスレッドが古いことを知っていますが、Vivから非常に良いヒントを与えられたにもかかわらず、この特定の問題にかなり苦労しました。
とにかく、私がここで思いついた解決策を共有したいと思いました。おそらくそれは途中で誰かを助けるでしょう。
_void Switch::on_sldSwitch_actionTriggered(int action) {
if(action != 7) ui->sldSwitch->setValue((action%2) ? 100 : 0);
}
void Switch::on_sldSwitch_sliderReleased() {
ui->sldSwitch->setValue((ui->sldSwitch->sliderPosition() >= 50) ? 100 : 0);
}
_
簡単な説明:actionTriggered
は、スライダーがキーボードでクリックまたは移動されるたびに呼び出されます。ドラッグすると、信号「7」が発生します。すぐにスナップしないように、アクション7はブロックされます。
右に移動すると、キーボードで3クリックしてクリックし、キーボードの「右」(または「下」)を押すと1を放出します。そのため、偶数ではないときに右にスナップしています。
左に移動すると、2または4を放出します。
sliderReleased()
は、ドラッグ後にマウスボタンを離すと呼び出されますが、この時点では、スライダーはまだ古い値を持っています(これにより、かなりの動作が発生しました)。したがって、スナップする正しい位置を取得するために、sliderPosition
ではなくvalue
を照会しました。
これが誰かの役に立つことを願っています。