33

QtのAndroid スイッチに相当する要素を使用しようとしています。QML で ToggleSwitch を見つけましたが、実際の C++ Qt ライブラリには何もありません。何か足りないだけですか、それともこのウィジェットを自分で再実装する必要がありますか?

4

10 に答える 10

41

次に例を示します。

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

ここに画像の説明を入力

2018 年 8 月 20 日更新

新素材スイッチウィジェット!

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

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

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

結果:

ここに画像の説明を入力

于 2016-06-29T14:27:54.510 に答える
16

@piccyの提案は、私が以前にそのようなトグルスイッチに対して行ったことです。いくつかの調整を加えます。

iOSのオン/オフスイッチと同様の動作をエミュレートする必要がありました。つまり、外部アニメーションなしでスライダーが0-1の制限がある場合には、段階的な動きは必要ありません。

したがって、私が行ったのは、スライダーの値の範囲をスライダーの最大幅と同じになるように設定することでした。

次に、スライダー解放信号を接続し、値が最大値の半分未満であるかどうかを確認します。その場合は、スライダー値を0に設定し、そうでない場合はスライダー値を最大値に設定します。

これにより、マウスを離したときに、優れたドラッグ効果と極端なクリップが得られます。

ドラッグせずに反対側をクリックしたときにスライダーを切り替えるだけの場合は、スライダー値の変更信号を接続し、新しい値がどちらかの極値に近いことを確認し、スライダーがダウン状態でない場合はスライダー値として設定します。スライダーが下がっている場合は、前のドラッグモーションが壊れる可能性があるため、スライダーの値を変更しないでください。

于 2013-02-11T00:19:05.230 に答える
4

また、範囲が 0 から 1 の水平方向の QSlider コントロールを使用してこれを行うこともできます。おそらく、最大幅を 50 程度に設定して、ダイアログの幅全体に拡張しないようにすることをお勧めします。 . 次に、スタイル シートで微調整して外観を改善するか、サブクラス化して自分でコントロールを描画します。見栄えを良くするのにそれほど多くのコードは必要ないかもしれません。

于 2013-02-08T20:39:40.477 に答える
3

さて、QCheckBoxを使用する必要があります。これはトグル スイッチではありませんが、同じことを行います。本当に別のビジュアルが必要な場合は、カスタム ウィジェットを作成する必要があります

于 2013-02-08T20:10:47.380 に答える
3

ダビタは、チェックボックスに関する彼の答えで正しいです。ただし、3 番目の例 (オン/オフ スイッチ) に似たものを探している場合は、そのために 2 つのQPushButtonを使用し、それらをcheckableに設定することができます。それらを同時に自動排他的にすると、準備が整います。

スタイルシートを使用して少し視覚的なスタイリングを行うことで、スポットに当てはまらない場合でも、近づくことができるはずです。

于 2013-02-08T20:17:01.183 に答える
1

QRadioButtonQPushButtonも参照してください。チェック可能で、「オン/オフ スイッチ トグル」のように、いくつかのスタイル シートまたはカスタム描画を作成できます。

于 2013-02-08T20:16:26.223 に答える
0

このスレッドが古いことは知っていますが、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しました。それだけです。

これが誰かに役立つことを願っています。

于 2015-09-22T13:08:35.907 に答える