当前位置: 首页 > 知识库问答 >
问题:

Qt中的拨动开关

谭奕
2023-03-14

我正在尝试使用一个与Qt中的Android Switches等效的元素。我在QML中找到了一个ToggleSwitch,但在实际的CQt库中一无所获。我只是错过了什么,还是我必须自己重新实现这个小部件?

共有3个答案

东门翰
2023-03-14

这里是@IMAN4K答案的Python 3/PyQt5实现。

对原始实施的改进:

  • 拇指大小可以大于/小于轨道大小
  • 使用当前应用的调色板进行着色
  • 单击
  • 时发出切换/单击信号
  • 各种其他修复
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()
宦文柏
2023-03-14

几个月前,我做了一个实现,其视觉效果需要与常见的桌面风格更加一致(C和Python版本可用;Python版本是原型,即它们的工作方式可能不同)。请注意,美学是使用 paintEvent 完全自定义的。不要期望根据系统的不同而产生不同的视觉效果。

C实现

注意:不要忘记includes(在我的示例中没有)。

用法:

SwitchButton* sbtn = new SwitchButton(this); // Default style is Style::ONOFF
bool current = sbtn->value();
sbtn->setValue(!current);

(...).马力士

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()
邴景山
2023-03-14

下面是一个示例:

< code>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;
};

开关.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();
    }

新材料开关小部件!

< code>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

开关.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-2020 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 final : public QVariantAnimation {
    Q_OBJECT
    Q_PROPERTY(QObject* targetObject READ targetObject WRITE setTargetObject)

  public:
    Animator(QObject* target, QObject* parent = nullptr);
    ~Animator() override;

    QObject* targetObject() const;
    void setTargetObject(QObject* target);

    inline bool isRunning() const {
        return state() == Running;
    }

  public slots:
    void setup(int duration, QEasingCurve easing = QEasingCurve::Linear);
    void interpolate(const QVariant& start, const QVariant& end);
    void setCurrentValue(const QVariant&);

  protected:
    void updateCurrentValue(const QVariant& value) override final;
    void updateState(QAbstractAnimation::State newState, QAbstractAnimation::State oldState) override final;

  private:
    QPointer<QObject> target;
};

class SelectionControl : public QAbstractButton {
    Q_OBJECT

  public:
    explicit SelectionControl(QWidget* parent = nullptr);
    ~SelectionControl() override;

    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 final : public SelectionControl {
    Q_OBJECT

    static constexpr auto CORNER_RADIUS = 8.0;
    static constexpr auto THUMB_RADIUS = 14.5;
    static constexpr auto SHADOW_ELEVATION = 2.0;

  public:
    explicit Switch(QWidget* parent = nullptr);
    Switch(const QString& text, QWidget* parent = nullptr);
    Switch(const QString& text, const QBrush&, QWidget* parent = nullptr);
    ~Switch() override;

    QSize sizeHint() const override final;

  protected:
    void paintEvent(QPaintEvent*) override final;
    void resizeEvent(QResizeEvent*) override final;
    void toggle(Qt::CheckState) override final;

    void init();
    QRect indicatorRect();
    QRect textRect();

    static inline QColor colorFromOpacity(const QColor& c, qreal opacity) {
        return QColor(c.red(), c.green(), c.blue(), qRound(opacity * 255.0));
    }
    static inline bool ltr(QWidget* w) {
        if (nullptr != 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

开关.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-2020 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"

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();
}

void Animator::setCurrentValue(const QVariant& value) {
    setStartValue(value);
    setEndValue(value);
    updateCurrentValue(currentValue());
}



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);
        //        qDebug() << thumbRect << thumbPosAniamtion->currentValue();
        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);

        /* draw text */
        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) {
        const QVariant posEnd = (style.indicatorMargin.left() + style.indicatorMargin.right() + 2) * 2;
        const QVariant thumbEnd = colorFromOpacity(style.thumbOnBrush, style.thumbOnOpacity);
        const QVariant trackEnd = colorFromOpacity(style.trackOnBrush, style.trackOnOpacity);

        if (!isVisible()) {
            thumbPosAniamtion->setCurrentValue(posEnd);
            thumbBrushAnimation->setCurrentValue(thumbEnd);
            trackBrushAnimation->setCurrentValue(trackEnd);
        } else {
            thumbPosAniamtion->interpolate(0, posEnd);
            thumbBrushAnimation->interpolate(colorFromOpacity(style.thumbOffBrush, style.thumbOffOpacity), thumbEnd);
            trackBrushAnimation->interpolate(colorFromOpacity(style.trackOffBrush, style.trackOffOpacity), trackEnd);
        }
    } else { // Qt::Unchecked
        const QVariant posEnd = 0;
        const QVariant thumbEnd = colorFromOpacity(style.thumbOffBrush, style.thumbOffOpacity);
        const QVariant trackEnd = colorFromOpacity(style.trackOffBrush, style.trackOffOpacity);

        if (!isVisible()) {
            thumbPosAniamtion->setCurrentValue(posEnd);
            thumbBrushAnimation->setCurrentValue(thumbEnd);
            trackBrushAnimation->setCurrentValue(trackEnd);
        } else {
            thumbPosAniamtion->interpolate(thumbPosAniamtion->currentValue().toInt(), posEnd);
            thumbBrushAnimation->interpolate(colorFromOpacity(style.thumbOnBrush, style.thumbOnOpacity), thumbEnd);
            trackBrushAnimation->interpolate(colorFromOpacity(style.trackOnBrush, style.trackOnOpacity), trackEnd);
        }
    }
}

主.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();
}

结果:

 类似资料:
  • 导语 自从2009年十月我在博客上写了第一篇QtCreator系列教程到现在,断断续续一共写了四十八篇,涵盖了Qt基础、绘图、数据库、Qt Quick和网络等主要应用方面的内容。虽然其中的内容很基础,但这也正是入门的读者所想要的,现在这个系列的读者已经超过了3万,很感谢大家对我的支持。因为当时开始写教程时并没有想得那么系统,所以就成了想到哪写哪。在现在看来,上来第一篇就是helloworld的编写

  • 我目前在一个Twilio子帐户和一个TwiML应用程序中工作,试图从一个基于web的客户端启动出站呼叫。 我正在使用。浏览器中的设备连接到固定电话。我暴露了一个公共endpoint(使用ngrok),并且TwiML App已成功配置为将呼叫请求POST到endpoint。我正在用

  • Qt Creator是Qt默认的集成开发环境。它由Qt的开发者们编写提供的。这个集成开发环境能够在大多数的桌面开发平台上使用,例如 Windows/Mac/Linux。我们也已经看到有些用户在嵌入式设备上使用Qt Creator。Qt Creator有着精简的用户界面,可以帮助开发者们高效的完成开发生产。Qt Creator 能够启动你的QtQuick用户界面,也可以用来编译c++代码到你的主机系

  • C.2.1 国际社区 下面是在线参考的一些国际网址: http://partners.trolltech.com/ http://lists.trolltech.com/qt-interest/ http://doc.trolltech.com/qq/ 可以从 http://doc.trolltech.com 中获取 Qt 的当前版和一些早期版本的在线参考文 档。这个网站也选摘了 Qt 季刊(Qt

  • 问题内容: 在Flutter中是否有任何现成的小部件或从何处开始(https://material.io/guidelines/components/buttons- floating-action-button.html#buttons-floating-action-button-transitions) in Flutter. 问题答案: 这是有关如何使用进行快速拨号的示意图.

  • 1.简介 Qt Demo 是 Qt 套件之一,它包含了大量的演示和示例程序,基本涵盖了 Qt 编程中的 主要类别,将它与 Qt Assistant 结合使用能够收到很好的效果。 2.运行 Qt Demo 要运行 Qt Demo,在 Windows 下,如果是可依次单击【开始】→【(所有)程序】→【Qt SDK by Nokia v2009.03(OpenSource)】→【Qt Demo】;在 X