行业知识
[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服务器发包?
下一篇:社区服务器怎么切换中文?