自定义的Qt开关按钮
这个控件比较简单,模仿现代应用程序常见的开关按钮绘制。通过这个案例你可以了解Qt动画的使用。在VS2015和Qt5.9上简单测试通过。下面是效果图:
下面给出代码,头文件:
class MSwitch : public QWidget { Q_OBJECT public: MSwitch(QWidget* parent = 0); QSize sizeHint() const override; bool isOpened() const; signals: void clicked(bool); private: void setButtonPos(float where); void paintEvent(QPaintEvent *event) override; void mousePressEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void enterEvent(QEvent *event) override; void leaveEvent(QEvent *event) override; private: bool opened; bool hover; float atWhere; /* [0, 1] */ QPoint pressPt; };
CPP文件(代码中变量atWhere是用来配合绘制动画的。另外需要指出的是在事件mouseReleaseEvent中播放动画的操作,没有考虑用户连续快速点击按钮的情况。在这种情况下会连续new QVariantAnimation,导致同时存在多个QVariantAnimation对象。不过经过我的测试,这也没有什么影响。如果读者觉得需要优化可以改一改。):
MSwitch::MSwitch(QWidget* parent) : QWidget(parent) { opened = false; hover = false; atWhere = 0; } void MSwitch::setButtonPos(float where) { atWhere = where; update(); } bool MSwitch::isOpened() const { return opened; } void MSwitch::paintEvent(QPaintEvent *) { QPainter painter(this); painter.setRenderHint(QPainter::Antialiasing); qreal rad = height() * 0.5; /* 圆半径 */ int xleft = rad; int xright = width() - rad; int xpos = xleft + (xright - xleft) * atWhere; painter.setPen(Qt::NoPen); painter.setBrush((xpos == xright) ? QColor(0, 170, 255) : QColor(173, 173, 173)); painter.drawRoundedRect(0, 0, width(), height(), rad, rad); if (hover) /* 鼠标悬停稍微提亮一点 */ { painter.setBrush(QColor(255, 255, 255, 63)); painter.drawRoundedRect(0, 0, width(), height(), rad, rad); } painter.setPen(QColor(213, 213, 213)); painter.setBrush(QColor(243, 243, 243)); painter.drawEllipse(QPointF(xpos, rad), rad - 1, rad - 1); } void MSwitch::mousePressEvent(QMouseEvent *event) { pressPt = event->pos(); } void MSwitch::mouseReleaseEvent(QMouseEvent *event) { if (pressPt == event->pos()) { opened = !opened; emit clicked(opened); QVariantAnimation* ani = new QVariantAnimation(this); ani->setStartValue(0.0f); ani->setEndValue(1.0f); ani->setDuration(200); ani->setDirection(opened ? QVariantAnimation::Forward : QVariantAnimation::Backward); connect(ani, &QVariantAnimation::valueChanged, this, [this](const QVariant& value) { setButtonPos(value.toFloat()); }); ani->start(QAbstractAnimation::DeleteWhenStopped); } } void MSwitch::enterEvent(QEvent *event) { hover = true; update(); } void MSwitch::leaveEvent(QEvent *event) { hover = false; update(); } QSize MSwitch::sizeHint() const { return QSize(42, 21); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具