标签:
在 详解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_OBJECT protected 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代码分析:
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();
最后实现的的效果如下:
标签:
原文地址:http://blog.csdn.net/mao19931004/article/details/52143770