Qt自定義開關按鈕控制元件

菜鳥清清發表於2020-11-16

Qt自定義開關按鈕控制元件

最近的專案需要在頁面中新增一個開關按鈕,樣式類似於iOS的wifi開關按鈕。
開狀態
關狀態

在網上借鑑了別人的程式碼,稍作修改可以呈現出想要的效果(๑ `▽´๑)

程式碼如下。

switchcontrol.h

#include <QWidget>
#include <QTimer>

class SwitchControl : public QWidget
{
    Q_OBJECT

public:
    explicit SwitchControl(QWidget *parent = 0);

    //返回開關狀態-開啟:true 關閉:false
    bool isToggled() const;

    //設定開關狀態
    void setToggled(bool checked);

    //設定背景顏色
    void setBackgroundColor(QColor color);

    //設定選中顏色
    void setCheckedColor(QColor color);

    //設定不可用顏色
    void setDisabledColor(QColor color);

protected:
    //繪製開關
    void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE;

    //滑鼠按下事件
    void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE;

    //滑鼠釋放事件-切換開關狀態、發射toggled()訊號
    void mouseReleaseEvent(QMouseEvent *event) Q_DECL_OVERRIDE;

    //大小改變事件
    void resizeEvent(QResizeEvent *event) Q_DECL_OVERRIDE;

    //預設大小
    QSize sizeHint() const Q_DECL_OVERRIDE;
    QSize minimumSizeHint() const Q_DECL_OVERRIDE;

signals:
    //狀態改變時,發射訊號
    void toggled(bool checked);

private slots:
    //狀態切換時,用於產生滑動效果
    void onTimeout();

private:
    bool m_bChecked;            //是否選中
    QColor m_background;        //背景顏色
    QColor m_checkedColor;      //選中顏色
    QColor m_disabledColor;     //不可用顏色
    QColor m_thumbColor;        //拇指顏色
    qreal m_radius;             //圓角
    qreal m_nX;                 //x點座標
    qreal m_nY;                 //y點座標
    qint16 m_nHeight;           //高度
    qint16 m_nMargin;           //外邊距
    QTimer m_timer;             //定時器
};

switchcontrol.cpp

#include <switchcontrol.h>
#include <QPainter>
#include <QMouseEvent>

SwitchControl::SwitchControl(QWidget *parent)
    :QWidget(parent),
      m_nHeight(38),
      m_bChecked(true),
      m_radius(19.0),
      m_nMargin(4),
      m_checkedColor(QColor(22,68,128)),
      m_thumbColor(QColor(102,102,102)),
      m_disabledColor(QColor(242,242,242)),
      m_background(QColor(242,242,242))
{
    //滑鼠滑過游標形狀-手型
    setCursor(Qt::PointingHandCursor);

    //連線訊號槽
    connect(&m_timer,SIGNAL(timeout()),this,SLOT(onTimeout()));
}

void SwitchControl::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    QPainter painter(this);
    painter.setPen(Qt::NoPen);
    painter.setRenderHint(QPainter::Antialiasing);

    QPainterPath path;
    QColor background;
    QColor thumbColor;
    qreal dOpacity;
    if(isEnabled()){    //可用狀態
        if(m_bChecked){    //開啟狀態
            background = m_background;
            thumbColor = m_checkedColor;
            dOpacity = 0.600;
        }else{      //關閉狀態
            background = m_background;
            thumbColor = m_thumbColor;
            dOpacity = 0.800;
        }
    }else{  //不可用狀態
        background = m_background;
        dOpacity = 0.260;
        thumbColor = m_disabledColor;
    }
    //繪製大橢圓
    painter.setBrush(background);
    painter.setOpacity(dOpacity);
    path.addRoundedRect(QRectF(m_nMargin, m_nMargin, width() - 2 * m_nMargin, height() - 2 * m_nMargin), m_radius, m_radius);
    painter.drawPath(path.simplified());

    //繪製小橢圓
    painter.setBrush(thumbColor);
    painter.setOpacity(1.0);
    painter.drawEllipse(QRectF(m_nX - (m_nHeight / 5), m_nY - (m_nHeight / 3.3), height() / 1.5, height() / 1.5));
}

//滑鼠按下事件
void SwitchControl::mousePressEvent(QMouseEvent *event)
{
    if(isEnabled()){
        if(event -> buttons() & Qt::LeftButton){
            event -> accept();
        }else{
            event -> ignore();
        }
    }
}

//滑鼠釋放事件-切換開關狀態、發射toggled()訊號
void SwitchControl::mouseReleaseEvent(QMouseEvent *event)
{
    if(isEnabled()){
        if((event->type() == QMouseEvent::MouseButtonRelease) && (event->button() == Qt::LeftButton)){
            event->accept();
            m_bChecked = !m_bChecked;
            emit toggled(m_bChecked);
            m_timer.start(10);
        }else{
            event->ignore();
        }
    }
}

//大小改變事件
void SwitchControl::resizeEvent(QResizeEvent *event)
{
    m_nX = m_nHeight / 2;
    m_nY = m_nHeight / 2;
    QWidget::resizeEvent(event);
}

//預設大小
QSize SwitchControl::sizeHint() const
{
    return minimumSizeHint();
}

//最小大小
QSize SwitchControl::minimumSizeHint() const
{
    return QSize(2 * (m_nHeight + m_nMargin),m_nHeight + 2 * m_nMargin);
}

//切換狀態-滑動
void SwitchControl::onTimeout()
{
    if(m_bChecked){
        m_nX += 1;
        if(m_nX >= width() - m_nHeight)
            m_timer.stop();
    }else{
        m_nX -= 1;
        if(m_nX <= m_nHeight / 2)
            m_timer.stop();
    }
    update();
}

//返回開關狀態-開啟:true 關閉:false
bool SwitchControl::isToggled() const
{
    return m_bChecked;
}

//設定開關狀態
void SwitchControl::setToggled(bool checked)
{
    m_bChecked = checked;
    m_timer.start(10);
}

//設定背景顏色
void SwitchControl::setBackgroundColor(QColor color)
{
    m_background = color;
}

//設定選中顏色
void SwitchControl::setCheckedColor(QColor color)
{
    m_checkedColor = color;
}

//設定不可用顏色
void SwitchControl::setDisabledColor(QColor color)
{
    m_disabledColor = color;
}

實際應用示例

MRSwitchControl = new SwitchControl(this);
MRSwitchControl -> move(570,735);
//設定狀態、樣式
MRSwitchControl -> setToggled(true);

//可設定槽函式控制按鈕的開關狀態
connect(MRSwitchControl,&SwitchControl::toggled,this,&SystemSetting::setMaskRecog);

相關文章