小工具知识网

当前位置: 首页 > 行业知识 > [Qt学习笔记]Qt实现自定义控件SwitchButton开关按钮

行业知识

[Qt学习笔记]Qt实现自定义控件SwitchButton开关按钮

2026-11-09 16:12:43 来源:互联网转载

1、功能介绍

在项目UI中使用较多的打开/关闭的开关按钮,一般都是找图片去做效果,比如说如下的图像来表征打开或关闭。

如果想要控件有打开/关闭的动画效果或比较好的视觉效果,这里就可以使用自定义控件,使用Painter来绘制控件。软件最终的效果如上图三:

2、主要的实现绘制代码

绘制背景区域

void SwitchButton::drawBackGround(QPainter *painter){    painter->save();    painter->setPen(Qt::NoPen);    QColor bgColor = m_checked ? m_bgColorOn : m_bgColorOff;    if (isEnabled()) {        bgColor.setAlpha(140);    }    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();}

这里引入了滑块动画效果,设定一个定时器,根据滑块的距离设置一个动画的效果

    m_timer = new QTimer(this);    m_timer->setInterval(30);    connect(m_timer, SIGNAL(timeout()), this, SLOT(UpdateValue()));void SwitchButton::UpdateValue(){    if (m_checked) {        if (m_startX stop();        }    } else {        if (m_startX > m_endX) {            m_startX -= m_step;        } else {            m_startX = m_endX;            m_timer->stop();        }    }    update();}

3、功能实现源码

switchButton.h

#ifndef SWITCHBUTTON_H#define SWITCHBUTTON_H#include #include #include #include class SwitchButton : public QWidget{    Q_OBJECTpublic:    explicit SwitchButton(QWidget *parent = nullptr);signals:    void statusChanged(bool checked);public slots:private slots:    void UpdateValue();private:    void drawBackGround(QPainter *painter);    void drawSlider(QPainter *painter);protected:    void paintEvent(QPaintEvent *event);    void mousePressEvent(QMouseEvent *event);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;    //滑块开始X轴坐标    int m_startX;    //滑块介绍X轴坐标    int m_endX;public:    int space()                 const;    int radius()                const;    bool checked()              const;    bool showText()             const;    bool showCircle()           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);//    void setStep(int step);//    void setStartX(int startX);//    void setEndX(int endX);};#endif // SWITCHBUTTON_H

switchButton.cpp

#pragma execution_character_set("utf-8")#include "SwitchButton.h"#include 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(21, 156, 119);    m_bgColorOff = QColor(111, 122, 126);    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(140);    }    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 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::showCircle() 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();    }}//void SwitchButton::setStep(int step)//{//    if (m_step != step) {//        m_step = step;//        update();//    }//}//void SwitchButton::setStartX(int startX)//{//}//void SwitchButton::setEndX(int endX)//{//}

4、效果与源码

控件实现的动态效果如下

本小例程的代码放到我的开源gitte项目里,欢迎一起学习,也希望能收获你的小星星。

源码SwitchButton

上一篇:怎么用liunx服务器发包?

下一篇:社区服务器怎么切换中文?