天天看点

Qt QWidget实现开关控件SwithButton(SlipButton)

前言

Qt做界面的时候常常会用到开关控件,类似于CheckButton有两种状态,只是界面表现形式不一样而已。本文通过QWidget类来实现一个开关控件SwitchBtn(有些平台上又称为SlipButton)。

首先来看看封装好的控件样式

正文

其中动画效果是通过QPropertyAnimation来实现的,按钮中间的圆是一张准备好的图片,而控件背景是通过当前状态然后用QPainter来绘制的。

话不多说,直接上代码

头文件

#include <QWidget>
#include <QPaintEvent>
#include <QPainterPath>
#include <QPropertyAnimation>
#include <QMouseEvent>
#include <QLabel>
class CTLSlipBtn : public QWidget
{
Q_OBJECT
public:
explicit CTLSlipBtn(int w,int h,QWidget *parent = 0);
~CTLSlipBtn();
void setBtnChecked(bool check);
protected:
void paintEvent(QPaintEvent* e);
void mouseReleaseEvent(QMouseEvent * e);
signals:
void sigClicked(bool);
private:
void _checkBtn();
private:
QLabel * m_pSwitchBtn;
bool           

源文件

#include "ctlslipbtn.h"
#include <QPainter>
#include "alcommonparameter.h"
CTLSlipBtn::CTLSlipBtn(int w, int h, QWidget *parent) :
QWidget(parent),
m_bIsChecked(false)
{
resize(w,h);
m_pSwitchBtn = new QLabel(this);
m_pSwitchBtn->setFixedSize(h,h);
m_pSwitchBtn->setPixmap(QPixmap("btn_switch.png"));
m_pSwitchBtn->move(QPointF(1,0).toPoint());
m_pTBtnBg = new QPainterPath();
m_pTBtnBg->moveTo(width(),height());
m_pTBtnBg->setFillRule(Qt::WindingFill);
m_pTBtnBg->addEllipse(w- h,0,h,h);
m_pTBtnBg->addEllipse(0,0,h,h);
m_pTBtnBg->addRect(h*0.5,0,w-h ,h);
m_pBtnAni = new QPropertyAnimation(m_pSwitchBtn,"pos",this);
m_pBtnAni->setEasingCurve(QEasingCurve::Linear);
m_pBtnAni->setDuration(100);
}
CTLSlipBtn::~CTLSlipBtn()
{
delete m_pBtnAni;
delete m_pTBtnBg;
}
void CTLSlipBtn::setBtnChecked(bool check)
{
m_bIsChecked = check;
if(check)
{
m_pSwitchBtn->move(QPointF(width()-m_pSwitchBtn->height()-1,0).toPoint());
}
else
{
m_pSwitchBtn->move(QPointF(1,0).toPoint());
}
}
void CTLSlipBtn::paintEvent(QPaintEvent *e)
{
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(Qt::NoPen);
if(m_bIsChecked)
{
painter.setBrush(QColor(34,169,173));
}
else
{
painter.setBrush(QColor(200,200,200));
}
painter.drawPath(*m_pTBtnBg);
QWidget::paintEvent(e);
}
void CTLSlipBtn::mouseReleaseEvent(QMouseEvent *e)
{
_checkBtn();
update();
emit sigClicked(m_bIsChecked);
QWidget::mouseReleaseEvent(e);
}
void CTLSlipBtn::_checkBtn()
{
if(m_pBtnAni)
{
if(m_pBtnAni->state() == QAbstractAnimation::Running)
{
return;
}
if(m_bIsChecked)
{
m_pBtnAni->setStartValue(QPointF(width()-height()-1,0).toPoint());
m_pBtnAni->setEndValue(QPointF(1,0).toPoint());
}
else
{
m_pBtnAni->setStartValue(QPointF(1,0).toPoint());
m_pBtnAni->setEndValue(QPointF(width()-height()-1,
0).toPoint());
}
m_pBtnAni->start();
m_bIsChecked = !m_bIsChecked;
}
}           

其中开关状态变化后会发出信号sigClicked(bool)

这里的控件背景都是固定写死的,为了灵活性,可以写一个接口单独控件背景颜色,比较简单,这里不再赘述。控件使用方式也很简单,直接初始化的时候传入控件的大小,然后连接对象的信号即可。

点击领取Qt学习资料+视频教程~

链接:http://docs.qq.com/doc/DUlVwTW1FZlZuWE9G