Qt QWidget實現開關控制元件SwithButton(SlipButton)
阿新 • • 發佈:2019-01-27
前言
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 m_bIsChecked;
QPainterPath* m_pTBtnBg;
QPropertyAnimation* m_pBtnAni;
};
原始檔
#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)
這裡的控制元件背景都是固定寫死的,為了靈活性,可以寫一個介面單獨控制元件背景顏色,比較簡單,這裡不再贅述。控制元件使用方式也很簡單,直接初始化的時候傳入控制元件的大小,然後連線物件的訊號即可。