当前位置: 首页 > news >正文

Qt-自定义按钮动画

一、绪论

效果视频:
https://live.csdn.net/v/500458

项目地址:https://github.com/orpheanlive/Qt-animation.git

二、代码

这里新建一个animation类方便移植。

animation.h

#ifndef ANIMATION_H
#define ANIMATION_H#include <QWidget>
#include <QPropertyAnimation>
#include <QPainter>
#include <QEnterEvent>class Animation : public QWidget
{Q_OBJECTQ_PROPERTY(qreal scaleFactor READ scaleFactor WRITE setScaleFactor NOTIFY scaleFactorChanged)public:explicit Animation(QWidget *parent = nullptr);~Animation() override = default;void setText(const QString &text);//设置显示文本void setPicture(const QString &picturePath);//设置图片路径qreal scaleFactor() const { return m_scaleFactor; }//获取当前缩放因子void setScaleFactor(qreal factor);//设置缩放因子signals:void scaleFactorChanged();//缩放因子变化信号protected://重写Qt事件处理函数void enterEvent(QEnterEvent *event) override;//鼠标进入事件void leaveEvent(QEvent *event) override;//鼠标离开事件void paintEvent(QPaintEvent *event) override;//绘制事件private slots:void updateAnimationState();//更新动画状态private:// 私有辅助方法void setupAnimations();   // 初始化动画系统void updatePixmapSize();  // 更新图片尺寸// 成员变量bool m_isHovered = false;     // 鼠标悬停状态标志qreal m_scaleFactor = 1.0;    // 当前缩放因子qreal m_normalScale = 1.0;    // 正常状态缩放值qreal m_hoverScale = 3.0;     // 悬停状态缩放值QString m_text;          // 显示的文本内容QString m_picturePath;   // 图片文件路径QPixmap m_pixmap;        // 图片对象QSize m_originalSize;    // 图片原始尺寸// 动画对象智能指针std::unique_ptr<QPropertyAnimation> m_enterAnimation;  // 进入动画std::unique_ptr<QPropertyAnimation> m_leaveAnimation;  // 离开动画
};#endif // ANIMATION_H

animation.cpp

#include "animation.h"
#include <QPainter>// 构造函数:初始化父组件并设置动画系统
Animation::Animation(QWidget *parent): QWidget(parent)
{setupAnimations();  // 调用动画初始化函数
}// 设置动画系统:创建并配置进入和离开动画
void Animation::setupAnimations()
{// 创建进入动画,绑定到scaleFactor属性m_enterAnimation = std::make_unique<QPropertyAnimation>(this, "scaleFactor");m_enterAnimation->setDuration(300);                    // 设置动画时长300msm_enterAnimation->setEasingCurve(QEasingCurve::OutCubic);  // 设置缓动曲线为OutCubic// 创建离开动画,同样绑定到scaleFactor属性m_leaveAnimation = std::make_unique<QPropertyAnimation>(this, "scaleFactor");m_leaveAnimation->setDuration(300);m_leaveAnimation->setEasingCurve(QEasingCurve::OutCubic);// 连接缩放因子变化信号到更新槽函数connect(this, &Animation::scaleFactorChanged, this, &Animation::updateAnimationState);
}// 设置显示文本并触发重绘
void Animation::setText(const QString &text)
{m_text = text;update();  // 请求重绘以显示新文本
}// 设置图片:加载图片文件并更新显示
void Animation::setPicture(const QString &picturePath)
{m_picturePath = picturePath;m_pixmap.load(picturePath);  // 从文件路径加载图片// 如果图片加载成功,保存原始尺寸并更新图片大小if (!m_pixmap.isNull()) {m_originalSize = m_pixmap.size();updatePixmapSize();}update();  // 请求重绘以显示新图片
}// 设置缩放因子:如果值发生变化则更新并发出信号
void Animation::setScaleFactor(qreal factor)
{// 使用模糊比较避免浮点数精度问题if (qFuzzyCompare(m_scaleFactor, factor))return;m_scaleFactor = factor;updatePixmapSize();        // 更新图片尺寸emit scaleFactorChanged(); // 发出缩放因子变化信号
}// 鼠标进入事件处理:启动进入动画
void Animation::enterEvent(QEnterEvent *event)
{Q_UNUSED(event)  // 标记未使用参数m_isHovered = true;  // 设置悬停状态// 配置并启动进入动画:从当前值缩放到悬停值m_enterAnimation->setStartValue(m_scaleFactor);m_enterAnimation->setEndValue(m_hoverScale);m_enterAnimation->start();
}// 鼠标离开事件处理:启动离开动画
void Animation::leaveEvent(QEvent *event)
{Q_UNUSED(event)m_isHovered = false;  // 清除悬停状态// 配置并启动离开动画:从当前值缩放到正常值m_leaveAnimation->setStartValue(m_scaleFactor);m_leaveAnimation->setEndValue(m_normalScale);m_leaveAnimation->start();
}// 绘制事件:渲染图片和文本
void Animation::paintEvent(QPaintEvent *event)
{Q_UNUSED(event)// 如果图片为空则直接返回if (m_pixmap.isNull())return;QPainter painter(this);painter.setRenderHint(QPainter::SmoothPixmapTransform);  // 设置平滑变换渲染提示// 计算缩放后的尺寸和居中位置const QSize scaledSize = m_originalSize * m_scaleFactor;const QPoint centerPoint((width() - scaledSize.width()) / 2, (height() - scaledSize.height()) / 2);// 绘制缩放后的图片到居中矩形区域painter.drawPixmap(QRect(centerPoint, scaledSize), m_pixmap);// 如果有文本,在底部居中绘制if (!m_text.isEmpty()) {painter.drawText(QRect(0, height() - 20, width(), 20), Qt::AlignCenter, m_text);}
}// 更新动画状态:触发重绘以反映动画变化
void Animation::updateAnimationState()
{update();  // 请求重绘
}// 更新图片尺寸:实际尺寸更新在paintEvent中处理
void Animation::updatePixmapSize()
{// 尺寸更新通过paintEvent自动处理
}

widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>class Widget : public QWidget
{Q_OBJECTpublic:explicit Widget(QWidget *parent = nullptr);~Widget() = default;
};#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "animation.h"
#include <QHBoxLayout>
#include <QVBoxLayout>Widget::Widget(QWidget *parent): QWidget(parent)
{// 设置窗口setStyleSheet("QWidget { background-color: #2b2b2b; color: #87ceeb; }");setWindowTitle("锦瑟的小程序");resize(800, 600);// 创建主布局QHBoxLayout *mainLayout = new QHBoxLayout(this);mainLayout->setSpacing(20);mainLayout->setContentsMargins(50, 50, 50, 50);// 手动创建 Animation 控件Animation *globeWidget = new Animation(this);globeWidget->setText("Globe");globeWidget->setPicture(":/icon/globe.svg");Animation *homeWidget = new Animation(this);homeWidget->setText("Home");homeWidget->setPicture(":/icon/home.svg");Animation *databaseWidget = new Animation(this);databaseWidget->setText("Database");databaseWidget->setPicture(":/icon/database.svg");Animation *downloadWidget = new Animation(this);downloadWidget->setText("Sun");downloadWidget->setPicture(":/icon/sun.svg");// 添加到布局mainLayout->addWidget(globeWidget);mainLayout->addWidget(homeWidget);mainLayout->addWidget(databaseWidget);mainLayout->addWidget(downloadWidget);setLayout(mainLayout);
}

http://www.dtcms.com/a/601189.html

相关文章:

  • llm course 5.6 学习笔记 同样的文本 模型输出的固定向量和计算出来的哈希值为什么携带的信息不同
  • 轻量化笔记推荐:Docker安装部署FlatNotes
  • 永康市住房建设局网站淮南网站建设
  • Facebook矩阵引流:从防封机制拆解
  • 新时代旅游职业教育系列教材编写研讨会成功举办
  • vue学习第一天
  • 各大编码编辑器的缓存目录迁移到D盘【未完待续】
  • 【XR开发系列】Unity第一印象:编辑器界面功能布局介绍(六大功能区域介绍)
  • 【轨物方案】轨物科技工业缝纫机物联网解决方案:以数智化重塑轻工制造价值链
  • django做的网站如何运行八爪鱼 wordpress
  • 定制型网站设计报价表wordpress长微博工具
  • [pdf、epub]350道《软件方法》强化自测题业务建模需求分析共298页(202511更新)
  • C++简单莫队(一)
  • 一键限制ACE反作弊进程优先级和CPU相关性(SGuardSvc64.exe/SGuard64.exe进程)
  • 网站建设兼职挣多少钱类似于wordpress的app
  • SMTP服务器终极测试指南:一站式解决邮件发送难题
  • MySQL: 操作系统对MySQL性能的影响及选型指南
  • 项目六:ChatBI智能分析与可视化(制造业经营决策ChatBI系统)
  • lf will be replace by crlf修复
  • 在Linux中查看Docker服务内存占用并重启超过警告的服务
  • Linux 虚拟机设置静态 IP 地址指南
  • 淄博电商网站建设网站建设实训 课程标准
  • InfiniBand(IB)比 RoCE 更快 的核心原因
  • python+django/flask的美食交流宣传系统vue
  • 基于DTW和HMM的语音识别仿真
  • 芯片,量子科技,脑部接口重点攻关企业名单
  • 融智兴科技携RFID洗涤标签亮相2025中国洗涤展
  • 【IQA技术专题】 基于多模态大模型的IQA Benchmark:Q-BENCH
  • 关于微软最新数据库引擎sqlserver2025 关于向量距离函数调用的问题
  • 网站建设维护合同范本检测WordPress网站的安全性