Qt自定义开关按钮控件

Qt自定义开关按钮控件

最近的项目需要在页面中添加一个开关按钮,样式类似于iOS的wifi开关按钮。
开状态
关状态

在网上借鉴了别人的代码,稍作修改可以呈现出想要的效果(๑ `▽´๑)

代码如下。

switchcontrol.h

#include 
#include 

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

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

你可能感兴趣的:(Qt,qt)