详解Qt动画框架(2)--- 实现网易云音乐tag切换
来源:互联网 发布:开淘宝店铺照片要求 编辑:程序博客网 时间:2024/06/06 21:50
在详解Qt的动画框架(一)介绍了关于Qt动画框架一些基础知识,在这一节中,将会实际的看到有关与动画框架的实现,该案例主要实现的具体是网易云音乐tag的切换,网易云音乐中的切换如图所示:
本文介绍的方法也可以达到这种切换的简易效果。
- 设计动画框架
首先我们需要设计对于动画框架,其需要的动画效果是什么?对于上图,我们需要的是三个tag可以不停的切换,可以抽象为左移以及右移,即一个tag从一个矩形区域,移动到另外的矩形区域,那么对于Tag的承载体选为什么较为合适呢?因为我们仅仅只需要图片的显示,因此QLabel引进足够,而且QLabel继承于QFrame(继承自QWidget),因此拥有geometry的属性,恰恰其类型是QRect,因此可以达到动画效果的所有需求,不需要另外的定制属性(property)。
- 动画实现
设计好动画框架后,既可以开始代码实现所有的动作了。以下是头文件的声明定义:
#ifndef MAINWINDOW_H#define MAINWINDOW_H#include <QMainWindow>#include<vector>using namespace std;class QLabel;class QToolBar;class QPropertyAnimation;class MainWindow : public QMainWindow{ Q_OBJECTprotected slots: void onTriggerAction(QAction *);public: MainWindow(QWidget *parent = 0); ~MainWindow();private: void moveLeft(); void moveRight(); QRect center_rect; QRect left_rect; QRect right_rect; QLabel *center_label; QLabel *left_label; QLabel *right_label; QPropertyAnimation *moveAnimation; QPropertyAnimation *moveAnimation_left; QPropertyAnimation *moveAnimation_right; int mainCnt; //下方的2个横线控件 QToolBar *transferBar; vector<QPixmap> label_group;};#endif // MAINWINDOW_H代码分析:
- 首先,横线控件是为了定义左移和右移动作的发起,它们是属于QToolBar的两个按钮控件,即transferBar。三个QLabel是动作的承载体,即target。是QPropertyAnimation构造时需要使用的。
- 然后是三个矩形框的定义,这是动画切换的起始位置的界定。
- 其次是三个QPropertyAnimation的定义,是控制三个QLabel的移动的。
- 最后mainCnt是为了很好的实时定位到tag切换到位置,从而控制动画的效果。
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent){ resize(1000,400); mainCnt=3; //在widget上画三个矩形框,实现动画切换,第一个大小为200 & 540 左右两边大小均为188*110 for(int label_num=0;label_num<3;label_num++) { QPixmap temp_label=QPixmap(":/images/"+QString::number(label_num+1)+".png"); label_group.push_back(temp_label); } int width=this->width(); int height=this->height();/** 设置中心控件的位置以及大小*/ int pos_x=(width-center_width)/2; int pos_y=(height-center_hieght)/2; center_rect.setRect(pos_x,pos_y,center_width,center_hieght); center_label =new QLabel(this); center_label->setPixmap(label_group[0]); //center_label->setScaledContents(true); center_label->setGeometry(pos_x,pos_y,center_width,center_hieght);//---------------------------------------------------------------------------------// /** 设置底部窗口转换的工具栏属性 */ transferBar = new QToolBar(this); transferBar->setGeometry(pos_x+center_width/2-40,pos_y+center_hieght+20,90,10); transferBar->setStyleSheet("background:transparent"); transferBar->setIconSize(QSize(20,5)); for(int actions_num=0;actions_num<2;actions_num++) { QAction *action=new QAction(QIcon(":/images/line.png"),"",transferBar); action->setData(actions_num); transferBar->addAction(action); } connect(transferBar,SIGNAL(actionTriggered(QAction *)),this,SLOT(onTriggerAction(QAction*))); /** 设置右边控件的位置和大小*/ right_rect.setRect(pos_x+center_width,pos_y+(center_hieght-margin_height),margin_width,margin_height); right_label =new QLabel(this); right_label->setPixmap(label_group[1]); //right_label->setScaledContents(true); right_label->setGeometry(pos_x+center_width,pos_y+(center_hieght-margin_height),margin_width,margin_height); /** 设置左边控件的位置和大小*/ pos_x=(pos_x-margin_width); pos_y=pos_y+(center_hieght-margin_height); left_rect.setRect(pos_x,pos_y,margin_width,margin_height); left_label =new QLabel(this); left_label->setPixmap(label_group[2]); //left_label->setScaledContents(true); left_label->setGeometry(pos_x,pos_y,margin_width,margin_height); center_label->raise();//------------------------------------------------------------------------------//}代码分析:
1、首先是定位三个矩形框的位置,为了达到和网易的效果,特意量了尺寸,定义如下:
#define center_width 540#define center_hieght 200#define margin_width 110#define margin_height 188骚年,如果感兴趣,可以草图画出来,就可以知道以上关于三个矩形框位置的计算方式是怎么得来的了。当然了,这仅仅只是我的计算方式,可以不予采来,嘻嘻。
2、其次是定位三个QLabel的位置,初始的时候,与三个矩形框保持一致。
3、最后是底部按钮的设计,主要是Icon的设计以及位置,还有toolBar的响应事件。
关键代码在于响应事件的设计,即两个函数moveLeft()以及moveRight();
#define ToLeft 0#define ToRight 1
void MainWindow::onTriggerAction(QAction *action){ int action_num=action->data().toInt(); if (action_num==ToLeft) moveLeft(); else if(action_num==ToRight) moveRight();}void MainWindow::moveLeft(){ mainCnt+=1; moveAnimation_left=new QPropertyAnimation(left_label,"geometry"); moveAnimation_left->setDuration(200); moveAnimation_left->setStartValue(left_rect); moveAnimation_left->setEndValue(right_rect); moveAnimation_left->setEasingCurve(QEasingCurve::Linear); moveAnimation_left->start(); moveAnimation=new QPropertyAnimation(center_label,"geometry"); moveAnimation->setDuration(200); moveAnimation->setStartValue(center_rect); moveAnimation->setEndValue(left_rect); moveAnimation->setEasingCurve(QEasingCurve::Linear); moveAnimation->start(); moveAnimation_right=new QPropertyAnimation(right_label,"geometry"); moveAnimation_right->setDuration(200); moveAnimation_right->setStartValue(right_rect); moveAnimation_right->setEndValue(center_rect); moveAnimation_right->setEasingCurve(QEasingCurve::Linear); moveAnimation_right->start(); /** 方向和label移动的方向恰恰相反 */ QRect rect(right_rect); right_rect=center_rect; center_rect=left_rect; left_rect=rect; if(mainCnt==6) mainCnt=3; if(mainCnt==4) { right_label->raise(); } else if(mainCnt==5) { left_label->raise(); } else if(mainCnt==1) { center_label->raise(); }}void MainWindow::moveRight(){ mainCnt-=1; moveAnimation_left=new QPropertyAnimation(left_label,"geometry"); moveAnimation_left->setDuration(200); moveAnimation_left->setStartValue(left_rect); moveAnimation_left->setEndValue(center_rect); moveAnimation_left->setEasingCurve(QEasingCurve::Linear); moveAnimation_left->start(); moveAnimation=new QPropertyAnimation(center_label,"geometry"); moveAnimation->setDuration(200); moveAnimation->setStartValue(center_rect); moveAnimation->setEndValue(right_rect); moveAnimation->setEasingCurve(QEasingCurve::Linear); moveAnimation->start(); moveAnimation_right=new QPropertyAnimation(right_label,"geometry"); moveAnimation_right->setDuration(200); moveAnimation_right->setStartValue(right_rect); moveAnimation_right->setEndValue(left_rect); moveAnimation_right->setEasingCurve(QEasingCurve::Linear); moveAnimation_right->start(); /** 方向和label移动的方向恰恰相反 */ QRect rect(left_rect); left_rect=center_rect; center_rect=right_rect; right_rect=rect; if(mainCnt==-1) mainCnt=3; if(mainCnt==2) { left_label->raise(); } else if(mainCnt==1) { right_label->raise(); } else if(mainCnt==0) { center_label->raise(); }}
代码分析:
1、首先是动画的构造以及初始化:
moveAnimation_left是控制left_label的动画的,左移是从left_rect移动到right_rect的位置,控制属性是geometry,移动的曲线方式是直线型的。
moveAnimation_center是控制center_label动画的,左移是从center_rect的位置移动到left_rect的位置
moveAnimation_right是控制right_label动画的,左移是从right_rect的位置移动到center_rect的位置。
2、其次是需要设置矩形框的位置,其设置效果为为了达到与label的同步,同时达到一种循环王府的效果。这点要重点理解。
3、mainCnt的控制,当达到移动图片的最大数量以后,需要重新开始,同时在不同的移动时,需要label展现效果,即置顶效果,raise();
最后实现的的效果如下:
- 详解Qt动画框架(2)--- 实现网易云音乐tag切换
- iOS 切换两个RootViewController动画 类似网易云音乐
- Qt音乐进度条的实现仿网易云音乐
- Qt模仿网易云音乐
- Swift实现类网易云音乐横向scroll menu切换菜单(一)
- Swift实现类网易云音乐横向scroll menu切换菜单(二)
- Qt动画框架详解
- Qt动画框架详解
- Qt/C++ 网易云api 在线播放音乐
- 详解Qt的动画框架(一)
- Swift版本仿网易云音乐播放音乐动画效果
- 用Java实现网易云音乐爬虫(非selenium)
- 网易云音乐登录信息加密算法详解
- Qt动画框架的实现
- 仿网易云音乐部分UI实现
- 网易云音乐锁屏界面实现
- 网易云音乐锁屏界面实现
- 网易云音乐使用中显示"请切换输出设备"
- 杭电3037Saving Beans
- activity生命周期理解
- LeetCode | Construct Binary Tree from Inorder and Postorder Traversal
- Java网络编程学习笔记(六)服务器Socket
- 【嵌入式】字符驱动开发框架
- 详解Qt动画框架(2)--- 实现网易云音乐tag切换
- 用Java模拟网卡、声卡继承PIC接口,实现网卡、声卡能与主板连接
- C语言实现字节流与十六进制字符串的相互转换
- 连接池
- 不同版本(2.3,2.4,2.5,3.0,3.1)的Servlet web.xml 头信息
- java字符串反转方法【全】
- Android自定义控件:如何使view动起来?
- Spring MVC
- Unity学习笔记 5th —— 第一人称FPS游戏制作