码迷,mamicode.com
首页 > 其他好文 > 详细

详解Qt动画框架(2)--- 实现网易云音乐tag切换

时间:2016-08-07 21:50:13      阅读:233      评论:0      收藏:0      [点我收藏+]

标签:

详解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
代码分析

  • 首先,横线控件是为了定义左移和右移动作的发起,它们是属于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切换

标签:

原文地址:http://blog.csdn.net/mao19931004/article/details/52143770

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!