Qt浅谈之二十六图片滑动效果

一、简介

        博客中发现有作者写的仿360的代码,觉得其中图片滑动的效果很有意思,特提取其中的代码。并加上类似mac的画面移动的动画效果。

二、详解

1、代码一:界面滑动(QWidget)

(1)sliderpicture.h

 

[html] view plain copy
 
  1. #ifndef SLIDERPICTURE_H  
  2. #define SLIDERPICTURE_H  
  3.   
  4. #include <QApplication>  
  5. #include <QWidget>  
  6. #include <QPushButton>  
  7. #include <QMouseEvent>  
  8. #include <QPainter>  
  9. #include <QLabel>  
  10. #include <QHBoxLayout>  
  11. #include <QVector>  
  12. #include <QDebug>  
  13. /************SliderPicture**************/  
  14. class PushButton;  
  15. class PixLabel;  
  16. class SliderPicture : public QWidget  
  17. {  
  18.     Q_OBJECT  
  19.   
  20. public:  
  21.     explicit SliderPicture(QWidget *parent = 0);  
  22.     ~SliderPicture();  
  23.   
  24. protected:  
  25.     void mousePressEvent(QMouseEvent *event);  
  26.     void mouseReleaseEvent(QMouseEvent *event);  
  27.     void mouseMoveEvent(QMouseEvent *event);  
  28.     void keyPressEvent(QKeyEvent *event);  
  29.   
  30. private:  
  31.     void moveCurrentPage(bool);  
  32.     void setLabelMove(bool);  
  33.   
  34. private:  
  35.     PushButton *close_button;  
  36.     QLabel *background_label;  
  37.     QPoint m_mouseSrcPos;  
  38.     QPoint m_mouseDstPos;  
  39.     bool mouse_press;  
  40.     bool mouse_move;  
  41.     bool label_move;  
  42.     int current_index;  
  43.     QLabel *total_label;  
  44.     QVector<PixLabel*>label_array;  
  45.   
  46.     int current_pos_x;  
  47.   
  48. private slots:  
  49.     void changeCurrentPage(PixLabel *label);  
  50. };  
  51.   
  52. /************PushButton**************/  
  53. class PushButton : public QPushButton  
  54. {  
  55.     Q_OBJECT  
  56.   
  57. public:  
  58.   
  59.     explicit PushButton(QWidget *parent = 0);  
  60.     ~PushButton();  
  61.     void setPicName(QString pic_name);  
  62.   
  63. protected:  
  64.   
  65.     void enterEvent(QEvent *);  
  66.     void leaveEvent(QEvent *);  
  67.     void mousePressEvent(QMouseEvent *event);  
  68.     void mouseReleaseEvent(QMouseEvent *event);  
  69.     void paintEvent(QPaintEvent *);  
  70.   
  71. private:  
  72.     enum ButtonStatus{NORMAL, ENTER, PRESS, NOSTATUS};  
  73.     ButtonStatus status;  
  74.     QString pic_name;  
  75.   
  76.     int btn_width;  
  77.     int btn_height;  
  78.     bool mouse_press;  
  79. };  
  80. /************CLabel**************/  
  81. class PixLabel : public QWidget  
  82. {  
  83.     Q_OBJECT  
  84. public:  
  85.     explicit PixLabel(QWidget *parent = 0);  
  86.     ~PixLabel();  
  87.   
  88.     void setPixmap(const QPixmap &);  
  89.     void setText(const QString &);  
  90.     void setMouseEnterFlag(bool);  
  91.     void setMousePressFlag(bool);  
  92.   
  93. protected:  
  94.     void enterEvent(QEvent *);  
  95.     void leaveEvent(QEvent *);  
  96.     void mousePressEvent(QMouseEvent *);  
  97.     void paintEvent(QPaintEvent *);  
  98.   
  99. signals:  
  100.     void signalLabelPress(PixLabel *);  
  101.   
  102. private:  
  103.     void initVariable();  
  104.     void initSetupUi();  
  105.     void createFrame();  
  106.     void createWidget();  
  107.     void createLayout();  
  108.     void paintWidget(int, QPainter *);  
  109.     bool getMouseEnterFlag();  
  110.     bool getMousePressFlag();  
  111.   
  112.     bool m_mouseEnterFlag;  
  113.     bool m_mousePressFlag;  
  114.   
  115.     QHBoxLayout *m_pHLayout;  
  116.     QLabel *m_pLabelIcon;  
  117.     QLabel *m_pLabelText;  
  118. };  
  119. #endif // SLIDERPICTURE_H  
(2)sliderpicture.cpp
[html] view plain copy
 
  1. #include "sliderpicture.h"  
  2.   
  3. SliderPicture::SliderPicture(QWidget *parent)  
  4.     : QWidget(parent)  
  5.     , mouse_press(false)  
  6.     , mouse_move(false)  
  7.     , label_move(true)  
  8.     , current_index(0)  
  9.     , current_pos_x(0)  
  10. {  
  11.     setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog);  
  12.     resize(680, 370);  
  13.   
  14.     background_label = new QLabel(this);  
  15.     background_label->setPixmap(QPixmap(":/bg_bottom"));  
  16.     background_label->setGeometry(QRect(0, 0, this->width(), this->height()));  
  17.   
  18.     QPixmap pixmap(QSize(this->width()*4, this->height()));  
  19.     QPainter painter(&pixmap);  
  20.     for(int i = 0; i 4; i++){  
  21.         painter.drawImage(QRect(this->width()*i, 0, this->width(), this->height()),  
  22.                           QImage(QString(":/desktop_%1").arg(i)));  
  23.     }  
  24.     total_label = new QLabel(this);  
  25.     total_label->resize(pixmap.size());  
  26.     total_label->setPixmap(pixmap);  
  27.     total_label->move(0, 0);  
  28.   
  29.     for(int index = 0; index 4; index++) {  
  30.         PixLabel *label = new PixLabel(this);  
  31.         label->resize(QSize(155, 45));  
  32.         label->setPixmap(QPixmap(QString(":/btn_%1").arg(index)));  
  33.         if (index == 0) {  
  34.             label->setText(tr("function"));  
  35.         }  
  36.         else if (index == 1) {  
  37.             label->setText(tr("clearcookie"));  
  38.         }  
  39.         else if (index == 2) {  
  40.             label->setText(tr("triggerman"));  
  41.         }  
  42.         else {  
  43.             label->setText(tr("booster"));  
  44.         }  
  45.         label->move(8+index*170, 319);  
  46.         connect(label, SIGNAL(signalLabelPress(PixLabel*)), this, SLOT(changeCurrentPage(PixLabel*)));  
  47.         label_array.append(label);  
  48.     }  
  49.     label_array.first()->setMousePressFlag(true);  
  50.     label_array.first()->setFocus();  
  51.   
  52.     close_button = new PushButton(this);  
  53.     close_button->setPicName(":/close");  
  54.     close_button->move(this->width()-close_button->width(), 0);  
  55.     close_button->setToolTip(tr("close"));  
  56.     connect(close_button, SIGNAL(clicked()), this, SLOT(close()));  
  57. }  
  58.   
  59. SliderPicture::~SliderPicture()  
  60. {  
  61.   
  62. }  
  63.   
  64. void SliderPicture::mousePressEvent(QMouseEvent *event)  
  65. {  
  66.     if(event->button() == Qt::LeftButton) {  
  67.         m_mouseSrcPos = event->pos();  
  68.         if(m_mouseSrcPos.y() <= 40) {  
  69.             mouse_move = true;  
  70.         }  
  71.         else {  
  72.             current_pos_x = total_label->x();  
  73.             mouse_press = true;  
  74.         }  
  75.     }  
  76.     else if(event->button() == Qt::RightButton) {  
  77.         if(label_move) {  
  78.             if(current_index > 0) {  
  79.                 current_index--;  
  80.                 moveCurrentPage(false);  //move right  
  81.             }  
  82.         }  
  83.     }  
  84. }  
  85.   
  86. void SliderPicture::mouseReleaseEvent(QMouseEvent *event)  
  87. {  
  88.     int xpos = 0;  
  89.     if (mouse_press) {  
  90.         if (label_move) {  
  91.             m_mouseDstPos = event->pos();  
  92.             xpos = m_mouseDstPos.x() - m_mouseSrcPos.x();  
  93.             if (xpos > 0) {                     //the plan is:move right  
  94.                 if(xpos >= 150) {               //mouse gap  
  95.                     if(current_index > 0) {     //move right  
  96.                         current_index--;  
  97.                         moveCurrentPage(false);  
  98.                     }  
  99.                     else {  
  100.                         moveCurrentPage(true);  //move left  
  101.                     }  
  102.                 }  
  103.                 else {  
  104.                      moveCurrentPage(true);     //move left  
  105.                 }  
  106.             }  
  107.             else {             //the plan is:move right  
  108.                 if(xpos <= -150)  
  109.                 {  
  110.                     if(current_index 4-1) {  
  111.                         current_index++;  
  112.                         moveCurrentPage(true);  //move left  
  113.                     }  
  114.                     else {  
  115.                         moveCurrentPage(false); //move right  
  116.                     }  
  117.                 }  
  118.                 else {  
  119.                     moveCurrentPage(false);     //move right  
  120.                 }  
  121.             }  
  122.         }  
  123.         mouse_press = false;  
  124.     }  
  125.     else if(mouse_move){  
  126.         mouse_move = false;  
  127.     }  
  128. }  
  129.   
  130. void SliderPicture::mouseMoveEvent(QMouseEvent *event)  
  131. {  
  132.     int xPos = 0;  
  133.     if(mouse_press) {  
  134.         if(label_move) {  
  135.             m_mouseDstPos = event->pos();  
  136.             xPos = m_mouseDstPos.x() - m_mouseSrcPos.x();  
  137.   
  138.             setLabelMove(false);  
  139.             total_label->move(current_pos_x + xPos, 0);  
  140.             setLabelMove(true);  
  141.         }  
  142.     }  
  143.     else if(mouse_move) {  
  144.         m_mouseDstPos = event->pos();  
  145.         this->move(this->pos() + m_mouseDstPos - m_mouseSrcPos);  
  146.     }  
  147. }  
  148.   
  149. void SliderPicture::keyPressEvent(QKeyEvent *event)  
  150. {  
  151.     if(label_move) {  
  152.         switch(event->key()) {  
  153.         case Qt::Key_Left:  
  154.         case Qt::Key_Up:  
  155.             if(current_index > 0) {  
  156.                 current_index--;  
  157.                 moveCurrentPage(false);    //move right  
  158.             }  
  159.             break;  
  160.         case Qt::Key_Right:  
  161.         case Qt::Key_Down:  
  162.             if(current_index 4-1) {  
  163.                 current_index++;  
  164.                 moveCurrentPage(true);     //move left  
  165.             }  
  166.             break;  
  167.         default:  
  168.             break;  
  169.         }  
  170.     }  
  171. }  
  172.   
  173. void SliderPicture::moveCurrentPage(bool direction)  
  174. {  
  175.     //change all label  
  176.     for(int i=0; i<4; i++) {  
  177.         if(i != current_index) {  
  178.             label_array.at(i)->setMousePressFlag(false);  
  179.         }  
  180.         else{  
  181.             label_array.at(i)->setMousePressFlag(true);  
  182.         }  
  183.     }  
  184.     //split point of picture  
  185.     //0-680 680-1360 1360-2040 2040-2720  
  186.     //true:left     false:right  
  187.   
  188.     //index=0, move -680*0  
  189.     //index=1, move -680*1  
  190.     //index=2, move-680*2  
  191.     //index=3, move-680*3  
  192.     setLabelMove(false);  
  193.     int current_pos_x = total_label->x();    //label position  
  194.     int dest_pos_x = -680 * current_index;  
  195.     if(direction) {  
  196.         while(current_pos_x > dest_pos_x) {  
  197.             total_label->move(current_pos_x-20, 0);  
  198.             current_pos_x = total_label->x();  
  199.             qApp->processEvents(QEventLoop::AllEvents);  
  200.         }  
  201.     }  
  202.     else {  
  203.         while(current_pos_x dest_pos_x) {  
  204.             total_label->move(current_pos_x+20, 0);  
  205.             current_pos_x = total_label->x();  
  206.             qApp->processEvents(QEventLoop::AllEvents);  
  207.         }  
  208.     }  
  209.     total_label->move(dest_pos_x, 0);  
  210.     setLabelMove(true);  
  211. }  
  212.   
  213. void SliderPicture::setLabelMove(bool enable)  
  214. {  
  215.     label_move = enable;  
  216. }  
  217.   
  218. void SliderPicture::changeCurrentPage(PixLabel *label)  
  219. {  
  220.     int index = 0;  
  221.     for(int iter = 0; iter 4; iter++) {  
  222.         if(label != label_array.at(iter)) {  
  223.             label_array.at(iter)->setMousePressFlag(false);  
  224.         }  
  225.         else {  
  226.             index = iter;                //get the clicked label of index  
  227.         }  
  228.     }  
  229.     if(index current_index) {          //move left  
  230.         while(index != current_index) {  
  231.             current_index--;  
  232.             moveCurrentPage(false);  
  233.         }  
  234.     }  
  235.     else if(index > current_index) {     //move right  
  236.         while(index != current_index) {  
  237.             current_index++;  
  238.             moveCurrentPage(true);  
  239.         }  
  240.     }  
  241.   
  242. }  
  243.   
  244. /************PushButton**************/  
  245. PushButton::PushButton(QWidget *parent)  
  246.     : QPushButton(parent)  
  247. {  
  248.     status = NORMAL;  
  249.     mouse_press = false;  
  250. }  
  251.   
  252. PushButton::~PushButton()  
  253. {  
  254.   
  255. }  
  256.   
  257. void PushButton::setPicName(QString pic_name)  
  258. {  
  259.     this->pic_name = pic_name;  
  260.     setFixedSize(QPixmap(pic_name).size());  
  261. }  
  262.   
  263. void PushButton::enterEvent(QEvent *)  
  264. {  
  265.     status = ENTER;  
  266.     update();  
  267. }  
  268.   
  269. void PushButton::mousePressEvent(QMouseEvent *event)  
  270. {  
  271.     if(event->button() == Qt::LeftButton) {  
  272.         mouse_press = true;  
  273.         status = PRESS;  
  274.         update();  
  275.     }  
  276. }  
  277.   
  278. void PushButton::mouseReleaseEvent(QMouseEvent *event)  
  279. {  
  280.     if(mouse_press  && this->rect().contains(event->pos())) {  
  281.         mouse_press = false;  
  282.         status = ENTER;  
  283.         update();  
  284.         emit clicked();  
  285.     }  
  286. }  
  287.   
  288. void PushButton::leaveEvent(QEvent *)  
  289. {  
  290.     status = NORMAL;  
  291.     update();  
  292. }  
  293.   
  294. void PushButton::paintEvent(QPaintEvent *)  
  295. {  
  296.     QPainter painter(this);  
  297.     QPixmap pixmap;  
  298.     switch(status) {  
  299.         case NORMAL: {  
  300.             pixmap.load(pic_name);  
  301.             break;  
  302.         }  
  303.         case ENTER: {  
  304.             pixmap.load(pic_name + QString("_hover"));  
  305.             break;  
  306.         }  
  307.         case PRESS: {  
  308.             pixmap.load(pic_name + QString("_pressed"));  
  309.             break;  
  310.         }  
  311.         case NOSTATUS: {  
  312.             pixmap.load(pic_name);  
  313.             break;  
  314.         }  
  315.         default:  
  316.             pixmap.load(pic_name);  
  317.     }  
  318.     painter.drawPixmap(rect(), pixmap);  
  319. }  
  320. /************PixLabel**************/  
  321. PixLabel::PixLabel(QWidget *parent)  
  322.     : QWidget(parent)  
  323. {  
  324.     initVariable();  
  325.     initSetupUi();  
  326. }  
  327.   
  328. PixLabel::~PixLabel()  
  329. {  
  330.     delete m_pLabelIcon;  
  331.     delete m_pLabelText;  
  332.     delete m_pHLayout;  
  333. }  
  334.   
  335. void PixLabel::setPixmap(const QPixmap &pixmap)  
  336. {  
  337.     m_pLabelIcon->setPixmap(pixmap.scaled(QSize(30, 30), Qt::KeepAspectRatio, Qt::SmoothTransformation));  
  338. }  
  339.   
  340. void PixLabel::setText(const QString &text)  
  341. {  
  342.     m_pLabelText->setText(text);  
  343. }  
  344.   
  345. void PixLabel::setMouseEnterFlag(bool flag)  
  346. {  
  347.     m_mouseEnterFlag = flag;  
  348.     this->update();  
  349. }  
  350.   
  351. void PixLabel::setMousePressFlag(bool flag)  
  352. {  
  353.     m_mousePressFlag = flag;  
  354.     this->update();  
  355. }  
  356.   
  357. void PixLabel::enterEvent(QEvent *)  
  358. {  
  359.     if(!getMousePressFlag()) {  
  360.         setMouseEnterFlag(true);  
  361.     }  
  362.     this->setCursor(Qt::PointingHandCursor);  
  363. }  
  364.   
  365. void PixLabel::leaveEvent(QEvent *)  
  366. {  
  367.     setMouseEnterFlag(false);  
  368. }  
  369.   
  370. void PixLabel::mousePressEvent(QMouseEvent *e)  
  371. {  
  372.     if(e->button() == Qt::LeftButton) {  
  373.         setMousePressFlag(true);  
  374.         emit signalLabelPress(this);  
  375.     }  
  376. }  
  377.   
  378. void PixLabel::paintEvent(QPaintEvent *e)  
  379. {  
  380.     QPainter painter(this);  
  381.     if(getMouseEnterFlag()) {  
  382.         paintWidget(50, &painter);  
  383.     }  
  384.     else if(getMousePressFlag()) {  
  385.         paintWidget(80, &painter);  
  386.     }  
  387.     QWidget::paintEvent(e);  
  388. }  
  389.   
  390. void PixLabel::initVariable()  
  391. {  
  392.     setMouseEnterFlag(false);  
  393.     setMousePressFlag(false);  
  394. }  
  395.   
  396. void PixLabel::initSetupUi()  
  397. {  
  398.     createFrame();  
  399.     createWidget();  
  400.     createLayout();  
  401. }  
  402.   
  403. void PixLabel::createFrame()  
  404. {  
  405.     this->setStyleSheet("QWidget{background:transparent;border:0px;color:white;font-weight:bold;font-size:16px;}");  
  406. }  
  407.   
  408. void PixLabel::createWidget()  
  409. {  
  410.     m_pLabelIcon = new QLabel(this);  
  411.     m_pLabelText = new QLabel(this);  
  412. }  
  413.   
  414. void PixLabel::createLayout()  
  415. {  
  416.     m_pHLayout = new QHBoxLayout;  
  417.     m_pHLayout->setSpacing(10);  
  418.     m_pHLayout->setContentsMargins(QMargins(5, 0, 5, 0));  
  419.     m_pHLayout->addWidget(m_pLabelIcon);  
  420.     m_pHLayout->addWidget(m_pLabelText);  
  421.     m_pHLayout->addStretch();  
  422.   
  423.     this->setLayout(m_pHLayout);  
  424. }  
  425.   
  426. void PixLabel::paintWidget(int transparency, QPainter *device)  
  427. {  
  428.     QPen pen(Qt::NoBrush, 1);  
  429.     device->setPen(pen);  
  430.     QLinearGradient linear(this->rect().topLeft(), this->rect().bottomLeft());  
  431.     linear.setColorAt(0, QColor(255, 255, 255, transparency));  
  432.   
  433.     QBrush brush(linear);  
  434.     device->setBrush(brush);  
  435.     device->drawRoundedRect(this->rect(), 2, 2);  
  436. }  
  437.   
  438. inline bool PixLabel::getMouseEnterFlag()  
  439. {  
  440.     return m_mouseEnterFlag;  
  441. }  
  442.   
  443. inline bool PixLabel::getMousePressFlag()  
  444. {  
  445.     return m_mousePressFlag;  
  446. }  
(3)main.cpp
[html] view plain copy
 
  1. #include "sliderpicture.h"  
  2. #include <QApplication>  
  3. #include <QTranslator>  
  4.   
  5. int main(int argc, char *argv[])  
  6. {  
  7.     QApplication a(argc, argv);  
  8.     QTranslator translator;  
  9.     translator.load("sliderpicture.qm",":/");  
  10.     a.installTranslator(&translator);  
  11.   
  12.     SliderPicture w;  
  13.     w.show();  
  14.   
  15.     return a.exec();  
  16. }  

       运行部分效果图(可以通过鼠标滑动或通过键盘方向键控制或者点击下方按钮):

 

2、代码二:按钮滑动(QGraphicsItem)

 

(1)parallaxhome.h

[html] view plain copy
 
  1. #ifndef PARALLAXHOME  
  2. #define PARALLAXHOME  
  3. #include <QtCore>  
  4. #include <QtGui>  
  5. #include <QtSvg>  
  6. class NaviBar : public QObject, public QGraphicsRectItem  
  7. {  
  8.     Q_OBJECT  
  9.   
  10. public:  
  11.     NaviBar(QGraphicsItem *parent = 0);  
  12.     void setPageOffset(qreal ofs);  
  13.     QRectF rect() const;  
  14.   
  15. signals:  
  16.     void pageSelected(int page);  
  17.   
  18. protected:  
  19.     void mousePressEvent(QGraphicsSceneMouseEvent *event);  
  20.     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);  
  21.   
  22. private:  
  23.     QList<QGraphicsSvgItem *> m_icons;  
  24.     QGraphicsRectItem *m_cursor;  
  25. };  
  26.   
  27. class ParallaxHome: public QGraphicsView  
  28. {  
  29.     Q_OBJECT  
  30. public:  
  31.     ParallaxHome(QWidget *parent = 0);  
  32.   
  33. private:  
  34.     QGraphicsScene m_scene;  
  35.     NaviBar *m_naviBar;  
  36.     QGraphicsPixmapItem *m_wallpaper;  
  37.     QTimeLine m_pageAnimator;  
  38.     qreal m_pageOffset;  
  39.     QList<QGraphicsPixmapItem*> m_items;  
  40.     QList<QPointF> m_positions;  
  41.     bool mouse_move;  
  42.     QPoint m_mouseSrcPos;  
  43.     QPoint m_mouseDstPos;  
  44.   
  45. signals:  
  46.     void pageChanged(int page);  
  47.   
  48. public slots:  
  49.     void slideRight();  
  50.     void slideLeft();  
  51.     void slideBy(int dx);  
  52.     void choosePage(int page);  
  53.   
  54. private slots:  
  55.     void shiftPage(int frame);  
  56.   
  57. protected:  
  58.     void resizeEvent(QResizeEvent *event);  
  59.     void keyPressEvent(QKeyEvent *event);  
  60.     void mousePressEvent(QMouseEvent *event);  
  61.     void mouseReleaseEvent(QMouseEvent *event);  
  62.     void mouseMoveEvent(QMouseEvent *event);  
  63.     void leaveEvent ( QEvent *event);  
  64.     void enterEvent(QEvent *event);  
  65.   
  66. private:  
  67.     void layoutScene();  
  68.     void setupScene();  
  69. };  
  70. #endif // PARALLAXHOME  
(2)parallaxhome.cpp
[html] view plain copy
 
  1. #include "parallaxhome.h"  
  2.   
  3. #define PAGE_COUNT 5  
  4. #define ICON_SIZE 50  
  5. #define ICON_PAD 4  
  6.   
  7. NaviBar::NaviBar(QGraphicsItem *parent)  
  8.     : QGraphicsRectItem(parent)  
  9. {  
  10.     setAcceptHoverEvents(true);  
  11.     setRect(0, 0, 5 * ICON_SIZE, ICON_SIZE);  
  12.     setPen(Qt::NoPen);  
  13.     QStringList names;  
  14.     names << "map" << "web" << "home" << "weather" << "contacts";  
  15.     for (int i = 0; i names.count(); ++i) {  
  16.         QString fname = names[i];  
  17.         fname.prepend(":/icons/");  
  18.         fname.append("-page.svg");  
  19.         QGraphicsSvgItem *icon = new QGraphicsSvgItem(fname);  
  20.         icon->setParentItem(this);  
  21.         icon->setCursor(Qt::PointingHandCursor);  
  22.         const int dim = ICON_SIZE - ICON_PAD * 2;  
  23.         qreal sw = dim / icon->boundingRect().width();  
  24.         qreal sh = dim / icon->boundingRect().height();  
  25.         icon->setTransform(QTransform().scale(sw, sh));  
  26.         icon->setZValue(2);  
  27.         m_icons <icon;  
  28.     }  
  29.     m_cursor = new QGraphicsRectItem;  
  30.     m_cursor->setParentItem(this);  
  31.     m_cursor->setRect(0, 0, ICON_SIZE, ICON_SIZE);  
  32.     m_cursor->setZValue(1);  
  33.     m_cursor->setPen(Qt::NoPen);  
  34.     m_cursor->setBrush(QColor(Qt::white));  
  35.     m_cursor->setOpacity(0.6);  
  36. }  
  37.   
  38. void NaviBar::setPageOffset(qreal ofs)  
  39. {  
  40.     m_cursor->setPos(ofs * ICON_SIZE, 0);  
  41.     for (int i = 0; i m_icons.count(); ++i) {  
  42.         int y = (i == static_cast<int>(ofs + 0.5)) ? ICON_PAD : ICON_PAD * 2;  
  43.         m_icons[i]->setPos(i * ICON_SIZE + ICON_PAD, y);  
  44.         m_icons[i]->setOpacity(1);  
  45.     }  
  46. }  
  47.   
  48. QRectF NaviBar::rect() const  
  49. {  
  50.     return QRectF(0, 0, 250, 50);  
  51. }  
  52.   
  53. void NaviBar::mousePressEvent(QGraphicsSceneMouseEvent *event)  
  54. {  
  55.     if (this->boundingRect().contains(event->pos())) {  
  56.         emit pageSelected(static_cast<int>(event->pos().x() / ICON_SIZE));  
  57.     }  
  58. }  
  59.   
  60. void NaviBar::paint(QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget)  
  61. {  
  62.     painter->setBrush(Qt::white);  
  63.     painter->setOpacity(0.2);  
  64.     painter->drawRect(option->rect);  
  65.     //painter->drawRect(option->rect.adjusted(-20, ICON_PAD, 20, 0));  
  66. }  
  67.   
  68. ParallaxHome::ParallaxHome(QWidget *parent)  
  69.         : QGraphicsView(parent)  
  70.         , m_pageOffset(-2)  
  71.         , mouse_move(false)  
  72. {  
  73.     resize(360, 504);  
  74.     setWindowFlags(Qt::FramelessWindowHint);  
  75.     setupScene();  
  76.     setScene(&m_scene);  
  77.     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);  
  78.     setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);  
  79.     setFrameShape(QFrame::NoFrame);  
  80.     setWindowTitle("Parallax Home");  
  81.   
  82.     connect(&m_pageAnimator, SIGNAL(frameChanged(int)), SLOT(shiftPage(int)));  
  83.     m_pageAnimator.setDuration(500);  
  84.     m_pageAnimator.setFrameRange(0, 100);  
  85.     m_pageAnimator.setCurveShape(QTimeLine::EaseInCurve);  
  86.   
  87.     pageChanged(static_cast<int>(m_pageOffset));  
  88.     move((QApplication::desktop()->width() - width())/2,  (QApplication::desktop()->height() - height())/2);  
  89. }  
  90.   
  91. void ParallaxHome::slideRight()  
  92. {  
  93.     if (m_pageAnimator.state() != QTimeLine::NotRunning)  
  94.         return;  
  95.     int edge = -(m_pageOffset - 1);  
  96.     if (edge PAGE_COUNT)  
  97.         slideBy(-1);  
  98. }  
  99.   
  100. void ParallaxHome::slideLeft()  
  101. {  
  102.     if (m_pageAnimator.state() != QTimeLine::NotRunning)  
  103.         return;  
  104.     if (m_pageOffset 0)  
  105.         slideBy(1);  
  106. }  
  107.   
  108. void ParallaxHome::slideBy(int dx)  
  109. {  
  110.     int start = m_pageOffset * 1000;  
  111.     int end = (m_pageOffset + dx) * 1000;  
  112.     m_pageAnimator.setFrameRange(start, end);  
  113.     m_pageAnimator.start();  
  114. }  
  115.   
  116. void ParallaxHome::choosePage(int page)  
  117. {  
  118.     if (m_pageAnimator.state() != QTimeLine::NotRunning)  
  119.         return;  
  120.     if (static_cast<int>(-m_pageOffset) == page)  
  121.         return;  
  122.     slideBy(-page - m_pageOffset);  
  123. }  
  124.   
  125. void ParallaxHome::shiftPage(int frame)  
  126. {  
  127.     int ww = width();  
  128.     int hh = height() - m_naviBar->rect().height();  
  129.   
  130.     int oldPage = static_cast<int>(-m_pageOffset);  
  131.     m_pageOffset = static_cast<qreal>(frame) / qreal(1000);  
  132.     int newPage = static_cast<int>(-m_pageOffset);  
  133.     m_naviBar->setPageOffset(-m_pageOffset);  
  134.     if (oldPage != newPage)  
  135.         emit pageChanged(newPage);  
  136.   
  137.     int ofs = m_pageOffset * ww;  
  138.     for (int i = 0; i m_items.count(); ++i) {  
  139.         QPointF pos = m_positions[i];  
  140.         QPointF xy(pos.x() * ww, pos.y() * hh);  
  141.         m_items[i]->setPos(xy + QPointF(ofs, 0));  
  142.     }  
  143.   
  144.     int center = m_wallpaper->pixmap().width() / 2;  
  145.     const int parallax = 3;  
  146.     int base = center - (ww / 2) - (PAGE_COUNT >> 1) * (ww / parallax);  
  147.     int wofs = base - m_pageOffset * ww / parallax;  
  148.     m_wallpaper->setPos(-wofs, 0);  
  149. }  
  150.   
  151. void ParallaxHome::resizeEvent(QResizeEvent *event)  
  152. {  
  153.     Q_UNUSED(event);  
  154.     layoutScene();  
  155. }  
  156.   
  157. void ParallaxHome::keyPressEvent(QKeyEvent *event)  
  158. {  
  159.     if (event->key() == Qt::Key_Right)  
  160.         slideRight();  
  161.     else if (event->key() == Qt::Key_Left)  
  162.         slideLeft();  
  163.     event->accept();  
  164. }  
  165.   
  166. void ParallaxHome::mousePressEvent(QMouseEvent *event)  
  167. {  
  168.     if(event->button() == Qt::LeftButton) {  
  169.         m_mouseSrcPos = event->pos();  
  170.         if(m_mouseSrcPos.y() <= 40) {  
  171.             mouse_move = true;  
  172.         }  
  173.     }  
  174.     QGraphicsView::mousePressEvent(event);  
  175. }  
  176.   
  177. void ParallaxHome::mouseReleaseEvent(QMouseEvent *event)  
  178. {  
  179.     if(mouse_move){  
  180.         mouse_move = false;  
  181.     }  
  182.     QGraphicsView::mouseReleaseEvent(event);  
  183. }  
  184.   
  185. void ParallaxHome::mouseMoveEvent(QMouseEvent *event)  
  186. {  
  187.     if(mouse_move) {  
  188.         m_mouseDstPos = event->pos();  
  189.         this->move(this->pos() + m_mouseDstPos - m_mouseSrcPos);  
  190.     }  
  191.     QGraphicsView::mouseMoveEvent(event);  
  192. }  
  193.   
  194. void ParallaxHome::leaveEvent(QEvent *event)  
  195. {  
  196. }  
  197.   
  198. void ParallaxHome::enterEvent(QEvent *event)  
  199. {  
  200. }  
  201.   
  202. void ParallaxHome::layoutScene()  
  203. {  
  204.     int ww = width();  
  205.     int hh = height();  
  206.   
  207.     m_scene.setSceneRect(0, 0, PAGE_COUNT * ww - 1, hh - 1);  
  208.     centerOn(ww / 2, hh / 2);  
  209.   
  210.     int nw = m_naviBar->rect().width();  
  211.     int nh = m_naviBar->rect().height();  
  212.     m_naviBar->setPos((ww - nw) / 2, hh - nh);  
  213.   
  214.     shiftPage(m_pageOffset * 1000);  
  215. }  
  216.   
  217. void ParallaxHome::setupScene()  
  218. {  
  219.     qsrand(QTime::currentTime().second());  
  220.   
  221.     QStringList names;  
  222.     names << "brownies" << "cookies" << "mussels" << "pizza" << "sushi";  
  223.     names << "chocolate" << "fish" << "pasta" << "puding" << "trouts";  
  224.   
  225.     for (int i = 0; i PAGE_COUNT * 2; ++i) {  
  226.         QString fname = names[i];  
  227.         fname.prepend(":/images/");  
  228.         fname.append(".jpg");  
  229.         QPixmap pixmap(fname);  
  230.         pixmap = pixmap.scaledToWidth(200);  
  231.         QGraphicsPixmapItem *item = m_scene.addPixmap(pixmap);  
  232.         m_items <item;  
  233.   
  234.         qreal x = (i >> 1) + (qrand() % 30) / 100.0;  
  235.         qreal y = (i & 1) / 2.0  + (qrand() % 20) / 100.0;  
  236.         m_positions <QPointF(x, y);  
  237.         item->setZValue(1);  
  238.     }  
  239.   
  240.     m_naviBar = new NaviBar;  
  241.     m_scene.addItem(m_naviBar);  
  242.     m_naviBar->setZValue(2);  
  243.     connect(m_naviBar, SIGNAL(pageSelected(int)), SLOT(choosePage(int)));  
  244.   
  245.     m_wallpaper = m_scene.addPixmap(QPixmap(":/icons/surfacing.png"));  
  246.     m_wallpaper->setZValue(0);  
  247.   
  248.     //m_scene.setItemIndexMethod(QGraphicsScene::NoIndex);  
  249.   
  250.     QPushButton *close_button = new QPushButton(this);  
  251.     close_button->resize(27, 22);  
  252.     close_button->setFocusPolicy(Qt::NoFocus);  
  253.     close_button->setStyleSheet("QPushButton{border-style:flat;background-image:url(:/icons/close.png);}QPushButton:hover{background-image:url(:/icons/close_hover.png);}QPushButton:hover:pressed{background-image:url(:/icons/close_pressed.png);}");  
  254.     close_button->setCursor(Qt::PointingHandCursor);  
  255.     close_button->raise();  
  256.     close_button->move(this->width()-close_button->width(), 0);  
  257.     close_button->setToolTip(tr("close"));  
  258.     connect(close_button, SIGNAL(clicked()), this, SLOT(close()));  
  259. }  
(3)main.cpp
[html] view plain copy
 
  1. #include "parallaxhome.h"  
  2.   
  3. int main(int argc, char *argv[])  
  4. {  
  5.     QApplication app(argc, argv);  
  6.   
  7.     ParallaxHome w;  
  8.     w.show();  
  9.   
  10.     return app.exec();  
  11. }  

 

运行效果图:

三、总结

(1)代码可以应用到相应的项目中,但相应功能还需要自定义开发。
(2)此源码已经打包上传到csdn上可登录下载(http://download.csdn.net/detail/taiyang1987912/8674131)。
(3)若有建议,请留言,在此先感谢!
 
0
posted @ 2016-04-06 23:13  苏博  阅读(2399)  评论(0编辑  收藏  举报