一、概述 最近想做一个炫酷的悬浮式菜单,考虑到菜单展开和美观,所以考虑学习下Qt的动画系统和状态机内容,打开QtCreator的示例教程浏览了下,大致发现教程中2DPainting程序和AnimatedTiles程序有所帮助,如下图所示,这两个demo讲述了怎么做一个展开动画,感兴趣的同学也可以直接参考 有了这两个demo之后,就可以开始动工写咱们自己的程序。二、效果展示 如下两幅图就是作者失效的两个悬浮菜单效果图,展示图1代码已上传至CSDN,不需要积分即可下载,效果图2代码暂时不开源,有需要的朋友可以进一步咨询 基础圆形菜单功能,代码已上传CSDNQt失效的PC端环形菜单、悬浮球菜单、展开动画 高级悬浮球菜单、支持二级菜单打开 三、实现代码 实现文件比较简单,只有头文件和实现文件,这里先主要放出头文件,然后讲解实现思路,具体实现细节可以通过下载源码进行具体了解1、菜单项 PopRingItem为菜单展开项、可以通过绑定外部QAction实现与普通菜单相同功能classPopRingItem:publicQLabel{QOBJECTpublic:PopRingItem(QWidgetparent0);PopRingItem();voidSetRadius(intradius);intGetRadius()const;voidBindAction(QActionaction);signals:voidMouseEvent(bool);protected:virtualvoidenterEvent(QEventevent)override;virtualvoidleaveEvent(QEventevent)override;virtualvoidpaintEvent(QPaintEventevent)override;protected:intmiRadius50;QActionmactActionnullptr;};2、悬浮球 悬浮球为菜单入口,继承自菜单项,与菜单项有相似功能classQVariantAnimation;classQPropertyAnimation;classPopRingMenu:publicPopRingItem{QOBJECTpublic:PopRingMenu(QWidgetparent0);PopRingMenu();signals:voidDoubleClicked();public:voidSetActions(constQVectorQActionacts);voidSetIcons(constQVectorQStringicons);voidSetAnimationEnabled(boolenabled);boolIsAnimationEnabled()const;voidSetSlowlyFade(boolenabled);boolIsSlowlyFade()const;voidSetDistanced(intdistance);intGetDistanced()const;voidSetStartAngle(intangle);intGetStartAngle()const;voidSetStepAngle(intangle);intGetStepAngle()const;voidSetNormalMenuSize(intsize);intGetNormalMenuSize()const;voidSetNormalItemSize(intsize);intGetNormalItemSize()const;protected:virtualvoidenterEvent(QEventevent)override;virtualvoidleaveEvent(QEventevent)override;virtualvoidmouseDoubleClickEvent(QMouseEventevent)override;virtualvoidtimerEvent(QTimerEventevent)override;virtualboolevent(QEventevent)override;privateslots:voidOnMouseEvent(bool);private:voidUpdateActions(intmsecond);voidExpandMenu();voidCollapseMenu();voidSlowlyFade();voidQuicklyLighter();boolIsUnderMouse()const;voidTryCollapseMenu();voidKillHideTimer();private:intmiDistance70;intmiStartAngle0;intmiStepAngle60;intmiMenuSize70;intmiItemSize60;intmiTimerID1;QPropertyAnimationmpOpacityAnimationnullptr;QVariantAnimationmpItemAnimationnullptr;QVectorPopRingItemmitems;};3、关键点初始化动画对象,指定动画时长和动画起始、终止值 动画具体实现函数未UpdateAction,根据当前动画进度值在动画起始值和终止值所占比例,进行计算当前动画时刻菜单项的位置和大小mpItemAnimationnewQVariantAnimation(this);mpItemAnimationsetEasingCurve(QEasingCurve::InCubic);mpItemAnimationsetStartValue(ShowMenuStartValue);mpItemAnimationsetEndValue(ShowMenuEndValue);mpItemAnimationsetDuration(ShowMenuDuration);connect(mpItemAnimation,QVariantAnimation::valueChanged,this,〔this〕(constQVariantv){UpdateActions(v。toInt());}); 鼠标进入悬浮球时,执行展开动画voidPopRingMenu::ExpandMenu(){if(mpItemAnimation){if(mpItemAnimationstate()!QAbstractAnimation::RunningmpItemAnimationcurrentValue()。toInt()!ShowMenuEndValue){mpItemAnimationsetDirection(QVariantAnimation::Forward);mpItemAnimationstart();}}else{UpdateActions(ShowMenuEndValue);}KillHideTimer();QuicklyLighter();} 鼠标离开悬浮球时,执行收起动画,与展开动画相反方向收起动画时有一个细节点,那就是鼠标hover在菜单项上时,也不能收起voidPopRingMenu::CollapseMenu(){if(falseIsUnderMouse()){if(mpItemAnimation){mpItemAnimationsetDirection(QVariantAnimation::Backward);mpItemAnimationstart();}else{UpdateActions(ShowMenuStartValue);}KillHideTimer();SlowlyFade();}} 展开和收起动画实现细节,根据动画指定帧数,按比例进行缩放和移动菜单项voidPopRingMenu::UpdateActions(intmsecond){intcurDistancemsecondmiDistanceShowMenuEndValue;for(inti0;imitems。size();i){PopRingItemitemmitems。at(i);doubleradiansqDegreesToRadians(miStepAnglei1。0miStartAngle);intoffxcurDistanceqCos(radians);intoffycurDistanceqSin(radians);itemmove(pos()QPoint(offx,offy));intcurSizemsecondmiItemSizeShowMenuEndValue;itemSetRadius(curSize);itemsetVisible(ShowMenuStartValue!msecond);};::SetWindowPos(HWND(winId()),HWNDTOPMOST,0,0,0,0,SWPNOMOVESWPNOSIZE);} 悬浮球指定时间未激活时,淡出,减少对用户视觉冲击voidPopRingMenu::SetSlowlyFade(boolenabled){if(enabled){if(nullptrmpOpacityAnimation){mpOpacityAnimationnewQPropertyAnimation(this,opacity);mpOpacityAnimationsetEasingCurve(QEasingCurve::OutCubic);mpOpacityAnimationsetStartValue(SlowlyStartValue);mpOpacityAnimationsetEndValue(SlowLyEndValue);mpOpacityAnimationsetDuration(SlowlyFadeDuration);}}else{if(mpOpacityAnimation){deletempOpacityAnimation;mpOpacityAnimationnullptr;}}}四、相关文章qt之菜单项定制Qt之QAbstractItemView右键菜单Qt弹出式菜单阴影Qt之自定义QLineEdit右键菜单Qt之股票组件自选股列表可以拖拽、右键常用菜单