QT自定义控件--滑动按钮

一、效果展示

在这里插入图片描述

二、绘制过程

2.1、控件分析

滑动按钮主要由背景框和滑块组成。当点击按钮的时候,滑块就会滑到另一边,相应的背景框和滑块的颜色都会发生切换,所以可以将任务细分为三个:绘制背景框、绘制滑块、实现点击滑动。

2.2、原理详解

滑动按键的功能是:点击按钮时,滑块会滑动到另一边;为了捕捉点击动作就必须写一个按钮点击事件mousePressEvent()。为了实现滑块平滑的移动,可以使用定时器逐次移动(例如每10ms移动1/50的移动距离)。产生点击之后,将按钮的状态翻转,再计算出滑块的目标位置,并开启定时器实现逐次移动,移动要根据滑块的初始位置和目标位置来判断:当开关关闭时发生点击,滑块要向右滑动,初始位置+=移动步长,直到初始位置等于目标位置;当开关开启时发生点击,滑块要向左滑动,初始位置-=移动步长,直到初始位置等于目标位置。然后每次定时器计时到达就触发重绘事件,因为绘制滑块时会参考初始位置,所以就实现了滑块平滑的移动。

2.3、绘制背景框

void SwitchButton::drawBg(QPainter *painter)
{
    painter->save();
    
    painter->setPen(Qt::NoPen);
    if (!checked) 
    {
        painter->setBrush(bgColorOff);
    } 
    else 
    {
        painter->setBrush(bgColorOn);
    }
	painter->drawRoundedRect(rect(), rectRadius, rectRadius);
    
    painter->restore();
}

2.4、绘制滑块

void SwitchButton::drawSlider(QPainter *painter)
{
    painter->save();
    
    painter->setPen(Qt::NoPen);
    if (!checked) {
        painter->setBrush(sliderColorOff);
    } else {
        painter->setBrush(sliderColorOn);
    }
    int sliderWidth = width() / 2 - space * 2;
    int sliderHeight = height() - space * 2;
    QRect sliderRect(startX + space, space, sliderWidth , sliderHeight);
    painter->drawRoundedRect(sliderRect, rectRadius, rectRadius);
   
    painter->restore();
}

2.5、其余代码

SwitchButton::SwitchButton(QWidget *parent): QWidget(parent)
{
    checked = false;

	//开、闭时背景颜色
    bgColorOff = QColor(225, 225, 225);
    bgColorOn = QColor(250, 250, 250);

	//开、闭时滑块颜色
    sliderColorOff = QColor(100, 100, 100);
    sliderColorOn = QColor(100, 184, 255);

    space = 2;  //背景间隔
    rectRadius = 5;

    step = width() / 50;  //步长

	//起始、目标位置
    startX = 0;
    endX = 0;

    timer = new QTimer(this);
    timer->setInterval(10);
    connect(timer, SIGNAL(timeout()), this, SLOT(updateValue()));

    setFont(QFont("Microsoft Yahei", 10));
}

void SwitchButton::mousePressEvent(QMouseEvent *)
{
    checked = !checked;
    emit checkedChanged(checked);

    //每次移动的步长为宽度的 50分之一
    step = width() / 50;

    //状态切换改变后自动计算终点坐标
    if (checked) 
    {
        endX = width() - width() / 2;
    } 
    else 
    {
        endX = 0;
    }

    timer->start();
}


void SwitchButton::updateValue()
{
    if (checked) {
        if (startX < endX) {
            startX = startX + step;
        } else {
            startX = endX;
            timer->stop();
        }
    } else {
        if (startX > endX) {
            startX = startX - step;
        } else {
            startX = endX;
            timer->stop();
        }
    }

    update();
}

void SwitchButton::resizeEvent(QResizeEvent *)
{
    //每次移动的步长为宽度的 50分之一
    step = width() / 50;

    //尺寸大小改变后自动设置起点坐标为终点
    if (checked) 
    {
    	startX = width() - width() / 2;    
    } 
    else 
    {
        startX = 0;
    }

    update();
}

void SwitchButton::paintEvent(QPaintEvent *)
{
    //绘制准备工作,启用反锯齿
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    //绘制背景
    drawBg(&painter);
    //绘制滑块
    drawSlider(&painter);
}

评论 7
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

贝勒里恩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值