qt自定义滑动按钮(美观且使用方便)

前言

某一次qt界面需要用到类似苹果上的滑动按钮,但发现qt中并没有类似的控件。百度之后发现有位博主的自己设计了这种控件,美观度和操作性都很高。但该博主没有介绍用法,所以特此记录,以便新手使用。

链接:原文链接


先上截图:

img

代码:

switchbutton.h

#ifndef switchbutton_H
#define switchbutton_H

#include <QWidget>
#include <QTimer>
#include <QColor>

class switchbutton : public QWidget
{
    Q_OBJECT

public:
    explicit switchbutton(QWidget *parent = 0);
    ~switchbutton(){}

signals:
    void statusChanged(bool checked);

public slots:
    void updateValue();

private:
    void drawBackGround(QPainter *painter);
    void drawSlider(QPainter *painter);

protected:
    void paintEvent(QPaintEvent *ev);
    void mousePressEvent(QMouseEvent *ev);

private:
    int m_space;                //滑块距离边界距离
    int m_radius;               //圆角角度

    bool m_checked;             //是否选中
    bool m_showText;            //是否显示文字
    bool m_showCircle;          //是否显示圆圈
    bool m_animation;           //是否使用动画

    QColor m_bgColorOn;         //打开时候的背景色
    QColor m_bgColorOff;        //关闭时候的背景色
    QColor m_sliderColorOn;     //打开时候滑块颜色
    QColor m_sliderColorOff;    //关闭时候滑块颜色
    QColor m_textColor;         //文字颜色

    QString m_textOn;           //打开时候的文字
    QString m_textOff;          //关闭时候的文字

    QTimer  *m_timer;            //动画定时器
    int     m_step;             //动画步长
    int     m_startX;           //滑块开始X轴坐标
    int     m_endX;             //滑块结束X轴坐标

public:
    int space()                 const;
    int radius()                const;
    bool checked()              const;
    bool showText()             const;
    bool showCircel()           const;
    bool animation()            const;

    QColor bgColorOn()          const;
    QColor bgColorOff()         const;
    QColor sliderColorOn()      const;
    QColor sliderColorOff()     const;
    QColor textColor()          const;

    QString textOn()            const;
    QString textOff()           const;

    int step()                  const;
    int startX()                const;
    int endX()                  const;


public Q_SLOTS:
    void setSpace(int space);
    void setRadius(int radius);
    void setChecked(bool checked);
    void setShowText(bool show);
    void setShowCircle(bool show);
    void setAnimation(bool ok);

    void setBgColorOn(const QColor &color);
    void setBgColorOff(const QColor &color);
    void setSliderColorOn(const QColor &color);
    void setSliderColorOff(const QColor &color);
    void setTextColor(const QColor &color);

    void setTextOn(const QString &text);
    void setTextOff(const QString &text);

};

#endif // switchbutton_H

switchbutton.cpp

#pragma execution_character_set("utf-8")
#include "switchbutton.h"
#include <QPainter>

switchbutton::switchbutton(QWidget *parent) : QWidget(parent)
{
    m_space = 2;
    m_radius = 5;
    m_checked = false;
    m_showText = true;
    m_showText = false;
    m_animation = true;

    m_bgColorOn = QColor(102, 205, 170);//设置按钮内部颜色
    m_bgColorOff = QColor(190, 190, 190);

    m_sliderColorOn = QColor(255, 255, 255);
    m_sliderColorOff = QColor(255, 255, 255);

    m_textColor = QColor(255, 255, 255);

    m_textOn = "开启";//设置按钮中的文字
    m_textOff = "关闭";

    m_step = 0;
    m_startX = 0;
    m_endX = 0;

    m_timer = new QTimer(this);
    m_timer->setInterval(30);
    connect(m_timer, SIGNAL(timeout()), this, SLOT(updateValue()));
}

void switchbutton::drawBackGround(QPainter *painter)
{
    painter->save();
    painter->setPen(Qt::NoPen);

    QColor bgColor = m_checked ? m_bgColorOn : m_bgColorOff;
    if (isEnabled()) {
        bgColor.setAlpha(150);
    }

    painter->setBrush(bgColor);

    QRect rect(0, 0, width(), height());
    int side = qMin(width(), height());

    //左侧半圆
    QPainterPath path1;
    path1.addEllipse(rect.x(), rect.y(), side, side);

    //右侧半圆
    QPainterPath path2;
    path2.addEllipse(rect.width() - side, rect.y(), side, side);

    //中间的矩形
    QPainterPath path3;
    path3.addRect(rect.x() + side / 2, rect.y(), rect.width() - side, height());

    QPainterPath path = path1 + path2 + path3;
    painter->drawPath(path);

    //绘制文本

    //滑块半径
    int sliderWidth = qMin(height(), width()) - m_space * 2 - 5;
    if (m_checked){
        QRect textRect(0, 0, width() - sliderWidth, height());
        painter->setPen(QPen(m_textColor));
        painter->drawText(textRect, Qt::AlignCenter, m_textOn);
    } else {
        QRect textRect(sliderWidth, 0, width() - sliderWidth, height());
        painter->setPen(QPen(m_textColor));
        painter->drawText(textRect, Qt::AlignCenter, m_textOff);
    }

    painter->restore();
}

void switchbutton::drawSlider(QPainter *painter)
{
    painter->save();
    painter->setPen(Qt::NoPen);

    QColor color = m_checked ? m_sliderColorOn : m_sliderColorOff;

    painter->setBrush(QBrush(color));

    int sliderWidth = qMin(width(), height()) - m_space * 2;
    QRect rect(m_space + m_startX, m_space, sliderWidth, sliderWidth);
    painter->drawEllipse(rect);

    painter->restore();
}

void switchbutton::paintEvent(QPaintEvent *ev)
{
    //启用反锯齿
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);

    //绘制背景
    drawBackGround(&painter);

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

void switchbutton::mousePressEvent(QMouseEvent *ev)
{
    Q_UNUSED(ev)

    m_checked = !m_checked;
    emit statusChanged(m_checked);

    //计算步长
    m_step = width() / 10;

    //计算滑块X轴终点坐标
    if (m_checked) {
        m_endX = width() - height();
    } else {
        m_endX = 0;
    }

    //判断是否使用动画
    if (m_animation) {
        m_timer->start();
    } else{
        m_startX = m_endX;
        update();
    }
}

void switchbutton::updateValue()
{
    if (m_checked) {
        if (m_startX < m_endX) {
            m_startX += m_step;
        } else {
            m_startX = m_endX;
            m_timer->stop();
        }
    } else {
        if (m_startX > m_endX) {
            m_startX -= m_step;
        } else {
            m_startX = m_endX;
            m_timer->stop();
        }
    }

    update();
}

int switchbutton::space() const
{
    return m_space;
}

int switchbutton::radius() const
{
    return m_radius;
}

bool switchbutton::checked() const
{
    return m_checked;
}

bool switchbutton::showText() const
{
    return m_showText;
}

bool switchbutton::showCircel() const
{
    return m_showCircle;
}

bool switchbutton::animation() const
{
    return m_animation;
}

QColor switchbutton::bgColorOn() const
{
    return m_bgColorOn;
}

QColor switchbutton::bgColorOff() const
{
    return m_bgColorOff;
}

QColor switchbutton::sliderColorOn() const
{
    return m_sliderColorOn;
}

QColor switchbutton::sliderColorOff() const
{
    return m_sliderColorOff;
}

QColor switchbutton::textColor() const
{
    return m_textColor;
}

QString switchbutton::textOn() const
{
    return m_textOn;
}

QString switchbutton::textOff() const
{
    return m_textOff;
}

int switchbutton::step() const
{
    return m_step;
}

int switchbutton::startX() const
{
    return m_startX;
}

int switchbutton::endX() const
{
    return m_endX;
}

void switchbutton::setSpace(int space)
{
    if (m_space != space) {
        m_space = space;
        update();
    }
}

void switchbutton::setRadius(int radius)
{
    if (m_radius != radius) {
        m_radius = radius;
        update();
    }
}

void switchbutton::setChecked(bool checked)
{
    if (m_checked != checked) {
        m_checked = checked;
        update();
    }
}

void switchbutton::setShowText(bool show)
{
    if (m_showText != show) {
        m_showText = show;
        update();
    }
}

void switchbutton::setShowCircle(bool show)
{
    if (m_showCircle != show) {
        m_showCircle = show;
        update();
    }
}

void switchbutton::setAnimation(bool ok)
{
    if (m_animation != ok) {
        m_animation = ok;
        update();
    }
}

void switchbutton::setBgColorOn(const QColor &color)
{
    if (m_bgColorOn != color) {
        m_bgColorOn = color;
        update();
    }
}

void switchbutton::setBgColorOff(const QColor &color)
{
    if (m_bgColorOff != color) {
        m_bgColorOff = color;
        update();
    }
}

void switchbutton::setSliderColorOn(const QColor &color)
{
    if (m_sliderColorOn != color) {
        m_sliderColorOn = color;
        update();
    }
}

void switchbutton::setSliderColorOff(const QColor &color)
{
    if (m_sliderColorOff != color) {
        m_sliderColorOff = color;
        update();
    }
}

void switchbutton::setTextColor(const QColor &color)
{
    if (m_textColor != color) {
        m_textColor = color;
        update();
    }
}

void switchbutton::setTextOn(const QString &text)
{
    if (m_textOn != text) {
        m_textOn = text;
        update();
    }
}

void switchbutton::setTextOff(const QString &text)
{
    if (m_textOff != text) {
        m_textOff = text;
        update();
    }
}

源码:

github源码链接

gitee源码链接


下面介绍一下按钮的基本使用,只需要switchbutton.h和switchbutton.cpp文件即可

  1. 先将两个类添加到代码中

  2. 因为我一直是将图形界面和代码分开的,所以只介绍通过qt designer的使用方法。在ui文件中,通过添加一个widget容器,然后把容器提升为类,就能灵活使用滑动按钮了。调整该widget的大小就是调整按钮的大小,我们可以任意调整按钮的布局的大小

    img

  3. 右键widget,选择提升为,注意基类名要和switchbutton.h的基类名保持一致。点击右边的添加,就会出现图片上方这个样子。选中后,右下角点击提升

image-20220518154631091

  1. qt designer右方可以看到widget变成了switchbutton类,也就是说这个widget就是switchbutton类的一个对象。我们可以通过控件名直接使用类中的变量和方法

image-20220518155020866

  1. 通过信号和槽来获取按钮的值,原博主设置了statusChanged信号和updateValue()槽,很方便的获取和设置按钮的值
connect(ui->widget, &switchbutton::statusChanged, this, &Widget::switchButton_Status);

img


码字不易,如果这篇博客对你有帮助,麻烦点赞收藏,非常感谢!有不对的地方

  • 21
    点赞
  • 74
    收藏
    觉得还不错? 一键收藏
  • 26
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值