Qt之悬浮球菜单
一、概述
最近想做一个炫酷的悬浮式菜单,考虑到菜单展开和美观,所以考虑学习下Qt的动画系统和状态机内容,打开QtCreator的示例教程浏览了下,大致发现教程中2D Painting程序和Animated Tiles程序有所帮助,如下图所示,这两个demo讲述了怎么做一个展开动画,感兴趣的同学也可以直接参考

有了这两个demo之后,就可以开始动工写咱们自己的程序。
二、效果展示
如下两幅图就是作者失效的两个悬浮菜单效果图,展示图1代码已上传至CSDN,不需要积分即可下载,效果图2代码暂时不开源,有需要的朋友可以进一步咨询
基础圆形菜单功能,代码已上传CSDN - Qt 失效的 PC 端环形菜单、悬浮球菜单、展开动画

高级悬浮球菜单、支持二级菜单打开

三、实现代码
实现文件比较简单,只有头文件和实现文件,这里先主要放出头文件,然后讲解实现思路,具体实现细节可以通过下载源码进行具体了解
1、菜单项
PopRingItem为菜单展开项、可以通过绑定外部QAction实现与普通菜单相同功能
class PopRingItem : public QLabel
{Q_OBJECTpublic:PopRingItem(QWidget *parent = 0);~PopRingItem();void SetRadius(int radius);int GetRadius() const;void BindAction(QAction * action);signals:void MouseEvent(bool);protected:virtual void enterEvent(QEvent * event) override;virtual void leaveEvent(QEvent * event) override;virtual void paintEvent(QPaintEvent * event) override;protected:int m_iRadius = 50;QAction * m_actAction = nullptr;
};
2、悬浮球
悬浮球为菜单入口,继承自菜单项,与菜单项有相似功能
class QVariantAnimation;
class QPropertyAnimation;
class PopRingMenu : public PopRingItem
{Q_OBJECTpublic:PopRingMenu(QWidget *parent = 0);~PopRingMenu();signals:void DoubleClicked();public:void SetActions(const QVector<QAction *> & acts);void SetIcons(const QVector<QString> & icons);void SetAnimationEnabled(bool enabled);bool IsAnimationEnabled() const;void SetSlowlyFade(bool enabled);bool IsSlowlyFade() const;void SetDistanced(int distance);int GetDistanced() const;void SetStartAngle(int angle);int GetStartAngle() const;void SetStepAngle(int angle);int GetStepAngle() const;void SetNormalMenuSize(int size);int GetNormalMenuSize() const;void SetNormalItemSize(int size);int GetNormalItemSize() const;protected:virtual void enterEvent(QEvent * event) override;virtual void leaveEvent(QEvent * event) override;virtual void mouseDoubleClickEvent(QMouseEvent * event) override;virtual void timerEvent(QTimerEvent * event) override;virtual bool event(QEvent * event) override;private slots:void OnMouseEvent(bool);private:void UpdateActions(int msecond);void ExpandMenu();void CollapseMenu();void SlowlyFade();void QuicklyLighter();bool IsUnderMouse() const;void TryCollapseMenu();void KillHideTimer();private:int m_iDistance = 70;int m_iStartAngle = 0;int m_iStepAngle = 60;int m_iMenuSize = 70;int m_iItemSize = 60;int m_iTimerID = -1;QPropertyAnimation * m_pOpacityAnimation = nullptr;QVariantAnimation * m_pItemAnimation = nullptr;QVector<PopRingItem *> m_items;
};
3、关键点
初始化动画对象,指定动画时长和动画起始、终止值
动画具体实现函数未UpdateAction,根据当前动画进度值在动画起始值和终止值所占比例,进行计算当前动画时刻菜单项的位置和大小
m_pItemAnimation = new QVariantAnimation(this);m_pItemAnimation->setEasingCurve(QEasingCurve::InCubic);
m_pItemAnimation->setStartValue(ShowMenuStartValue);
m_pItemAnimation->setEndValue(ShowMenuEndValue);
m_pItemAnimation->setDuration(ShowMenuDuration);connect(m_pItemAnimation, &QVariantAnimation::valueChanged, this, [this](const QVariant & v){UpdateActions(v.toInt());
});
鼠标进入悬浮球时,执行展开动画
void PopRingMenu::ExpandMenu()
{if (m_pItemAnimation){if (m_pItemAnimation->state() != QAbstractAnimation::Running&& m_pItemAnimation->currentValue().toInt() != ShowMenuEndValue){m_pItemAnimation->setDirection(QVariantAnimation::Forward);m_pItemAnimation->start();}}else{UpdateActions(ShowMenuEndValue);}KillHideTimer();QuicklyLighter();
}
鼠标离开悬浮球时,执行收起动画,与展开动画相反方向收起动画时有一个细节点,那就是鼠标hover在菜单项上时,也不能收起
void PopRingMenu::CollapseMenu()
{if (false == IsUnderMouse()){if (m_pItemAnimation){m_pItemAnimation->setDirection(QVariantAnimation::Backward);m_pItemAnimation->start();}else{UpdateActions(ShowMenuStartValue);}KillHideTimer();SlowlyFade();}
}
展开和收起动画实现细节,根据动画指定帧数,按比例进行缩放和移动菜单项
void PopRingMenu::UpdateActions(int msecond)
{int curDistance = msecond * m_iDistance / ShowMenuEndValue;for (int i = 0; i < m_items.size(); ++i){PopRingItem * item = m_items.at(i);double radians = qDegreesToRadians(m_iStepAngle * i * 1.0 + m_iStartAngle);int offx = curDistance * qCos(radians);int offy = curDistance * qSin(radians);item->move(pos() + QPoint(offx, offy));int curSize = msecond * m_iItemSize / ShowMenuEndValue;item->SetRadius(curSize);item->setVisible(ShowMenuStartValue != msecond);};::SetWindowPos(HWND(winId()), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
}
悬浮球指定时间未激活时,淡出,减少对用户视觉冲击
void PopRingMenu::SetSlowlyFade(bool enabled)
{if (enabled){if (nullptr == m_pOpacityAnimation){m_pOpacityAnimation = new QPropertyAnimation(this, "opacity");m_pOpacityAnimation->setEasingCurve(QEasingCurve::OutCubic);m_pOpacityAnimation->setStartValue(SlowlyStartValue);m_pOpacityAnimation->setEndValue(SlowLyEndValue);m_pOpacityAnimation->setDuration(SlowlyFadeDuration);}}else{if (m_pOpacityAnimation){delete m_pOpacityAnimation;m_pOpacityAnimation = nullptr;}}
}
相关文章:
Qt之悬浮球菜单
一、概述 最近想做一个炫酷的悬浮式菜单,考虑到菜单展开和美观,所以考虑学习下Qt的动画系统和状态机内容,打开QtCreator的示例教程浏览了下,大致发现教程中2D Painting程序和Animated Tiles程序有所帮助,如下图所示&a…...
易优cms attribute 栏目属性列表
attribute 栏目属性列表 attribute 栏目属性列表 [基础用法] 标签:attribute 描述:获取栏目的属性列表,或者单独获取某个属性值。 用法: {eyou:attribute typeauto} {$attr.name}:{$attr.value} {/eyou:attri…...
表格中的table-layout属性讲解
表格中的table-layout属性讲解 定义和用法 tableLayout 属性用来显示表格单元格、行、列的算法规则。 table-layout有三个属性值:auto、fixed、inherit。 fixed:固定表格布局 固定表格布局与自动表格布局相比,允许浏览器更快地对表格进行布…...
【MFA】windows环境下,使用Montreal-Forced-Aligner训练并对齐音频
文章目录一、安装MFA1.安装anaconda2.创建并进入虚拟环境3.安装pyTorch二、训练新的声学模型1.确保数据集的格式正确2.训练声音模型-导出模型和对齐文件3.报错处理1.遇到类似: Command ‘[‘createdb’,–host‘ ’, ‘Librispeech’]’ returned non-zero exit sta…...
C语言实验小项目实例源码大全订票信息管理系统贪吃蛇图书商品管理网络通信等
wx供重浩:创享日记 对话框发送:c项目 获取完整源码源文件视频讲解环境资源包文档说明等 包括火车订票系统、学生个人消费管理系统、超级万年历、学生信息管理系统、网络通信编程、商品管理系统、通讯录管理系统、企业员工管理系统、贪吃蛇游戏、图书管理…...
电脑图片损坏是怎么回事
电脑图片损坏是怎么回事?对于经常使用电脑的我们,总是会下载各种各样的图片,用于平时的使用中。但难免会遇到莫名其妙就损坏的图片文件,一旦发生这种情况,要如何才能修复损坏的图片呢?下面小编为大家带来常用的修复方…...
【论文研读】无人机飞行模拟仿真平台设计
无人机飞行模拟仿真平台设计 摘要: 为提高飞行控制算法的研发效率,降低研发成本,基于数字孪生技术设计一个无人机硬件在环飞行模拟仿真平台。从几何、物理和行为3个方面研究无人机数字模型构建方法,将物理实体以数字化方式呈现。设计一种多元融合场景建模法,依据属…...
【算法题】2379. 得到 K 个黑块的最少涂色次数
插: 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 坚持不懈,越努力越幸运,大家一起学习鸭~~~ 题目: 给你一个长度为 n 下标从 0 开始的…...
DJ1-3 计算机网络和因特网
目录 一、物理介质 1. 双绞线 2. 同轴电缆 3. 光纤线缆 4. 无线电磁波 二、端系统上的 Internet 服务 1. 面向连接的服务 TCP(Transmission Control Protocol) 2. 无连接的服务 UDP(User Datagram Protocol) TCP 和 UD…...
Git学习笔记(六)-标签管理
发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本。将来无论什么时候,取某个标签的版本,就是把那个打标签的时刻的历史版本取出来。所以,标签…...
Semaphore 源码解读
一、Semaphore Semaphore 通过设置一个固定数值的信号量,并发时线程通过 acquire() 获取一个信号量,如果能成功获得则可以继续执行,否则将阻塞等待,当某个线程使用 release() 释放一个信号量时,被阻塞的线程则可以被唤…...
RZ/G2L工业核心板U盘读写速率测试
1. 测试对象HD-G2L-IOT基于HD-G2L-CORE工业级核心板设计,双路千兆网口、双路CAN-bus、2路RS-232、2路RS-485、DSI、LCD、4G/5G、WiFi、CSI摄像头接口等,接口丰富,适用于工业现场应用需求,亦方便用户评估核心板及CPU的性能。HD-G2L…...
《SQL与数据库基础》18. MySQL管理
SQL - MySQL管理MySQL管理系统数据库常用工具mysqlmysqladminmysqlbinlogmysqlshowmysqldumpmysqlimportsource本文以 MySQL 为例 MySQL管理 系统数据库 Mysql数据库安装完成后,自带了以下四个数据库,具体作用如下: 数据库含义mysql存储My…...
达梦关系型数据库
达梦关系型数据库一、DM8 安装1. 安装包下载2. Docker 安装3. Linux 安装4. Windows 安装二、DM 管理工具三、命令行交互工具 DIsql四、DM8 SQL使用1. 创建模式2. 创建表3. 修改表4. 读写数据5. 查看库下所有的表名6. 查看表字段信息GitHub: link. 欢迎star国产自主研发的大型…...
Postgresql | 执行计划
SQL优化主要从三个角度进行: (1)扫描方式; (2)连接方式; (3)连接顺序。 如果解决好这三方面的问题,那么这条SQL的执行效率就基本上是靠谱的。看懂SQL的执行计…...
Vue3之父子组件通过事件通信
前言 组件间传值的章节我们知道父组件给子组件传值的时候,使用v-bind的方式定义一个属性传值,子组件根据这个属性名去接收父组件的值,但是假如子组件想给父组件一些反馈呢?就不能使用这种方式来,而是使用事件的方式&a…...
在云服务器安装tomcat和mysql
将 linux 系统安装包解压到指定目录进入 bin 目录执行./startup.sh 命令启动服务器执行./shutdown.sh 关闭服务器在浏览器中访问虚拟机中的 tomcat ip端口具体操作入下解压tomcat压缩包解压,输入tom按table键自动补全tar -zxvf 启动tomcat进入bin目录在linux启动to…...
IO多路复用(select、poll、epoll网络编程)
目录一、高级IO相关1.1 同步通信和异步通信1.2 阻塞与非阻塞1.3 fcntl 函数二、五种IO模型2.1 阻塞式IO模型2.2 非阻塞式IO模型2.3 多路复用IO模型2.4 信号驱动式IO模型2.5 异步IO模型三、认识IO多路复用四、select4.1 认识select函数4.2 select函数原型4.3 select网络编程4.4 …...
Spark单机伪分布式环境搭建、完全分布式环境搭建、Spark-on-yarn模式搭建
搭建Spark需要先配置好scala环境。三种Spark环境搭建互不关联,都是从零开始搭建。如果将文章中的配置文件修改内容复制粘贴的话,所有配置文件添加的内容后面的注释记得删除,可能会报错。保险一点删除最好。Scala环境搭建上传安装包解压并重命…...
C++网络编程(一)本地socket通信
C网络编程(一) socket通信 前言 本次内容简单描述C网络通信中,采用socket连接客户端与服务器端的方法,以及过程中所涉及的函数概要与部分函数使用细节。记录本人C网络学习的过程。 网络通信的Socket socket,即“插座”,在网络中译作中文“套接字”,应…...
2.Vue编写一个app
1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
CSS3相关知识点
CSS3相关知识点 CSS3私有前缀私有前缀私有前缀存在的意义常见浏览器的私有前缀 CSS3基本语法CSS3 新增长度单位CSS3 新增颜色设置方式CSS3 新增选择器CSS3 新增盒模型相关属性box-sizing 怪异盒模型resize调整盒子大小box-shadow 盒子阴影opacity 不透明度 CSS3 新增背景属性ba…...
虚幻基础:角色旋转
能帮到你的话,就给个赞吧 😘 文章目录 移动组件使用控制器所需旋转:组件 使用 控制器旋转将旋转朝向运动:组件 使用 移动方向旋转 控制器旋转和移动旋转 缺点移动旋转:必须移动才能旋转,不移动不旋转控制器…...
6.9本日总结
一、英语 复习默写list11list18,订正07年第3篇阅读 二、数学 学习线代第一讲,写15讲课后题 三、408 学习计组第二章,写计组习题 四、总结 明天结束线代第一章和计组第二章 五、明日计划 英语:复习l默写sit12list17&#…...
自定义线程池1.2
自定义线程池 1.2 1. 简介 上次我们实现了 1.1 版本,将线程池中的线程数量交给使用者决定,并且将线程的创建延迟到任务提交的时候,在本文中我们将对这个版本进行如下的优化: 在新建线程时交给线程一个任务。让线程在某种情况下…...
免费批量Markdown转Word工具
免费批量Markdown转Word工具 一款简单易用的批量Markdown文档转换工具,支持将多个Markdown文件一键转换为Word文档。完全免费,无需安装,解压即用! 官方网站 访问官方展示页面了解更多信息:http://mutou888.com/pro…...
Linux信号保存与处理机制详解
Linux信号的保存与处理涉及多个关键机制,以下是详细的总结: 1. 信号的保存 进程描述符(task_struct):每个进程的PCB中包含信号相关信息。 pending信号集:记录已到达但未处理的信号(未决信号&a…...
【Docker 02】Docker 安装
🌈 一、各版本的平台支持情况 ⭐ 1. Server 版本 Server 版本的 Docker 就只有个命令行,没有界面。 Platformx86_64 / amd64arm64 / aarch64arm(32 - bit)s390xCentOs√√Debian√√√Fedora√√Raspbian√RHEL√SLES√Ubuntu√√√√Binaries√√√ …...
