參考博客地址https://blog.csdn.net/liang19890820/article/details/52164289
大神提供了很好的思路,我在原文章的思路上理解若有不正確的,歡迎指正
基本原理如下:
繪制滑動開關的原理如下:


SwBtn.h檔案代碼如下 ——相關注釋我都寫了自己的理解
#ifndef SWBTN_H
#define SWBTN_H
#include <QWidget>
#include <QTimer>
class SWBtn : public QWidget
{
Q_OBJECT
public:
explicit SWBtn(QWidget *parent = nullptr);
bool SwBtn_isChecked() const; //回傳開關狀態 打開——true 關閉——false
void setSwBtn_Status(bool check); //設定開關狀態
void setSwBtn_BackgroundColor(QColor color); //設定背景顏色
void setSwBtn_CheckedColor(QColor color); //設定選中顏色
void setSwBtn_DisabilityColor(QColor color); //設定不可用的顏色
void setSwBtn_WidgetSize(int m_width,int m_height); //設定整個按鍵視窗大小
protected:
void paintEvent(QPaintEvent *event) override; //重寫繪圖事件——繪制按鈕
//重寫滑鼠左鍵按壓事件 Q_DECL_OVERRIDE(這個宏可以用來宣告一個覆寫的虛函式) override在這里等于這個宏
void mousePressEvent(QMouseEvent *event) Q_DECL_OVERRIDE/*等同于Q_DECL_OVERRIDE*/; //override c++11特性
//切記一定要對虛函式進行重新實作 不然未重新實作虛函式 override會使得報錯
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 SwBtn_SWITCH(bool check);
private slots:
void SwBtn_Slide(); //槽函式實作 圓形滑動
private:
bool m_SwBtn_Status; //開關狀態
QColor m_SwBtn_background; // 背景顏色
QColor m_SwBtn_checkedColor; // 選中顏色
QColor m_SwBtn_disabilityColor; // 不可用顏色
QColor m_SwBtn_thumbColor; // 小圓圈顏色
qreal m_SwBtn_radius; // 圓角
qreal m_SwBtn_X; // 視窗x點坐標
qreal m_SwBtn_Y; // 視窗y點坐標
qint16 m_SwBtn_Height; // 高度
qint16 m_SwBtn_Margin; // 外邊距
QTimer m_SwBtn_timer; // 定時器
};
#endif // SWBTN_H
SwBtn.cpp檔案具體實作如下:相關注釋也寫好了
/**************頭檔案******************/
#include "swbtn.h"
#include <QPainter>
#include <QMouseEvent>
/*****************END*****************/
SWBtn::SWBtn(QWidget *parent) : QWidget(parent),
m_SwBtn_Status(false),
m_SwBtn_background(Qt::black),
// m_SwBtn_checkedColor(0,150,136),
m_SwBtn_checkedColor(255,000,000),
m_SwBtn_disabilityColor(190,190,190),
m_SwBtn_thumbColor(Qt::white),
m_SwBtn_radius(12), //半圓半徑
m_SwBtn_Height(24), //視窗高度
m_SwBtn_Margin(5) //視窗邊距
//切記,以上建構式要按自己的私有屬性中的成員順序來賦值,不然會報錯
{
/*this->*/setCursor(Qt::PointingHandCursor); //設定滑鼠游標在小部件上的形狀 此處為手型
//QT4 信號與槽實作 此處是時間變化改變轉換開關滑動時狀態
connect(&m_SwBtn_timer,SIGNAL(timeout()),this,SLOT(SwBtn_Slide()));
}
//回傳開關狀態
bool SWBtn::SwBtn_isChecked() const
{
return m_SwBtn_Status;
}
//設定開關狀態
void SWBtn::setSwBtn_Status(bool check)
{
m_SwBtn_Status=check;
m_SwBtn_timer.start(10);
}
//設定背景顏色
void SWBtn::setSwBtn_BackgroundColor(QColor color)
{
m_SwBtn_background=color;
}
//設定選中顏色
void SWBtn::setSwBtn_CheckedColor(QColor color)
{
m_SwBtn_checkedColor=color;
}
//設定不可用時顏色
void SWBtn::setSwBtn_DisabilityColor(QColor color)
{
m_SwBtn_disabilityColor=color;
}
//設定整個按鍵視窗寬度和高度
void SWBtn::setSwBtn_WidgetSize(int m_width, int m_height)
{
this->m_SwBtn_Height=m_width-m_height;
this->m_SwBtn_Margin=m_height-(m_width/2);
this->m_SwBtn_radius=m_SwBtn_Height/2;
update();
}
void SWBtn::paintEvent(QPaintEvent *event)
{
/* Q_UNUSED指示編譯器沒有在函式體中使用指定名稱的形參,
* 這可以用來抑制編譯器警告,同時允許在函式的簽名中定義有意義的引數名,*/
Q_UNUSED(event);
QPainter painter(this);
painter.setPen(Qt::NoPen); //設定畫筆
painter.setRenderHint(QPainter::Antialiasing); //設定消除邊緣鋸齒
QPainterPath path;
QColor background; //背景色
QColor thumbColor; //小圓顏色
qreal pellucidity; //透明度引數 浮點型
if(isEnabled()){ //是否可用狀態
if(m_SwBtn_Status){ //打開狀態
background=m_SwBtn_checkedColor;
thumbColor=m_SwBtn_checkedColor;
pellucidity=0.6;
}
else{ //關閉狀態
background=m_SwBtn_background;
thumbColor=m_SwBtn_thumbColor;
pellucidity=0.8;
}
}
else{ //不可用狀態
background=m_SwBtn_background;
thumbColor=m_SwBtn_disabilityColor;
pellucidity=0.2;
}
//繪制背景圓角矩形
painter.setBrush(background); //設定畫刷
painter.setOpacity(pellucidity); //設定透明度
//設定圓角矩形引數 QRectF(x,y,長,高) x半徑 y半徑 (3,3)左上角 矩形(32*16) 半徑(8,8)
path.addRoundedRect(QRectF(m_SwBtn_Margin,
m_SwBtn_Margin,
width()-2*m_SwBtn_Margin,
height()-2*m_SwBtn_Margin),
m_SwBtn_radius,
m_SwBtn_radius);
painter.drawPath(path.simplified()); //加載路徑
//繪制小圓圈
painter.setBrush(thumbColor);
painter.setOpacity(1);
//繪制矩形中的橢圓 給定一個矩形 回傳貼著邊的橢圓 (22*22)
// painter.drawEllipse(QRectF(m_SwBtn_X-(m_SwBtn_Height/2),
// m_SwBtn_Y-(m_SwBtn_Height/2),
// height(),
// height()));
painter.drawEllipse(QRectF(m_SwBtn_X/*-(m_SwBtn_Height/2)*/,
m_SwBtn_Y/*-(m_SwBtn_Height/2)*/,
height(),
height()));
}
//滑鼠按下事件
void SWBtn::mousePressEvent(QMouseEvent *event)
{
if(isEnabled()){
//判斷是否左鍵安按下
if(event->button()==Qt::LeftButton){ //**
event->accept();
}
else
event->ignore();
}
}
//滑鼠釋放按鍵 發射狀態改變信號
void SWBtn::mouseReleaseEvent(QMouseEvent *event)
{
if(isEnabled()){
if((event->type()==QMouseEvent::MouseButtonRelease)&&(event->button()==Qt::LeftButton)){
event->accept();
m_SwBtn_Status=!m_SwBtn_Status; //改變當前開關狀態
emit SwBtn_SWITCH(m_SwBtn_Status); //發射改變以后的狀態
m_SwBtn_timer.start(10); //定時器10ms回應一次
}
else{
event->ignore(); //忽略該事件
}
}
}
//重現大小改變事件
void SWBtn::resizeEvent(QResizeEvent *event)
{
// m_SwBtn_X=m_SwBtn_Height/2; //x=8
// m_SwBtn_Y=m_SwBtn_Height/2; //y=8
m_SwBtn_X=0;
m_SwBtn_Y=0;
QWidget::resizeEvent(event);
}
//回傳默認建議大小
QSize SWBtn::sizeHint() const
{
return minimumSizeHint();
}
//回傳建議最小大小
QSize SWBtn::minimumSizeHint() const
{
//若按建構式指定大小 則尺寸為2*(16+3),16+2*3 尺寸為(38*22)像素
return QSize(2*(m_SwBtn_Height+m_SwBtn_Margin),m_SwBtn_Height+2*m_SwBtn_Margin);
}
//滑動槽函式定義 改變小圓圈的位置 每10ms重繪一次繪圖事件
void SWBtn::SwBtn_Slide()
{
// if(m_SwBtn_Status){ //打開狀態
// m_SwBtn_X+=1;
// if(m_SwBtn_X>=width()-m_SwBtn_Height) //x到22時
// m_SwBtn_timer.stop();
// }
// else{
// m_SwBtn_X-=1;
// if(m_SwBtn_X<=m_SwBtn_Height/2) //x到8時
// m_SwBtn_timer.stop();
// }
if(m_SwBtn_Status){ //打開狀態
m_SwBtn_X+=1;
if(m_SwBtn_X>=width()-height()) //x到16時 直接更新X坐標為寬度減高度
m_SwBtn_timer.stop();
}
else{
m_SwBtn_X-=1;
if(m_SwBtn_X<=0) //x到0時 X坐標直接從0開始
m_SwBtn_timer.stop();
}
update(); //更新繪圖事件
}
具體的實作代碼,在別的Widget視窗實作如下:
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
BTN1=new SWBtn(ui->widget_1);
BTN2=new SWBtn(ui->widget_1);
BTN1->move(50,50);
BTN2->move(50,100);
BTN3=new MY_SwitchButton(ui->widget_1);
BTN3->move(50,150);
}
Widget::~Widget()
{
delete ui;
}
具體實作的效果圖如下所示:

歡迎交流討論,目前也是一個正在學習QT的學習者,歡迎大家過來指正討論,
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/292766.html
標籤:其他
