1. 程式人生 > >Qt QWidget實現開關控制元件SwithButton(SlipButton)

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 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)
這裡的控制元件背景都是固定寫死的,為了靈活性,可以寫一個介面單獨控制元件背景顏色,比較簡單,這裡不再贅述。控制元件使用方式也很簡單,直接初始化的時候傳入控制元件的大小,然後連線物件的訊號即可。