Qt浅谈之二十六图片滑动效果
2015-05-07 22:40
351 查看
一、简介
博客中发现有作者写的仿360的代码,觉得其中图片滑动的效果很有意思,特提取其中的代码。并加上类似mac的画面移动的动画效果。
二、详解
1、代码一:界面滑动(QWidget)
(1)sliderpicture.h#ifndef SLIDERPICTURE_H #define SLIDERPICTURE_H #include <QApplication> #include <QWidget> #include <QPushButton> #include <QMouseEvent> #include <QPainter> #include <QLabel> #include <QHBoxLayout> #include <QVector> #include <QDebug> /************SliderPicture**************/ class PushButton; class PixLabel; class SliderPicture : public QWidget { Q_OBJECT public: explicit SliderPicture(QWidget *parent = 0); ~SliderPicture(); protected: void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void keyPressEvent(QKeyEvent *event); private: void moveCurrentPage(bool); void setLabelMove(bool); private: PushButton *close_button; QLabel *background_label; QPoint m_mouseSrcPos; QPoint m_mouseDstPos; bool mouse_press; bool mouse_move; bool label_move; int current_index; QLabel *total_label; QVector<PixLabel*>label_array; int current_pos_x; private slots: void changeCurrentPage(PixLabel *label); }; /************PushButton**************/ class PushButton : public QPushButton { Q_OBJECT public: explicit PushButton(QWidget *parent = 0); ~PushButton(); void setPicName(QString pic_name); protected: void enterEvent(QEvent *); void leaveEvent(QEvent *); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void paintEvent(QPaintEvent *); private: enum ButtonStatus{NORMAL, ENTER, PRESS, NOSTATUS}; ButtonStatus status; QString pic_name; int btn_width; int btn_height; bool mouse_press; }; /************CLabel**************/ class PixLabel : public QWidget { Q_OBJECT public: explicit PixLabel(QWidget *parent = 0); ~PixLabel(); void setPixmap(const QPixmap &); void setText(const QString &); void setMouseEnterFlag(bool); void setMousePressFlag(bool); protected: void enterEvent(QEvent *); void leaveEvent(QEvent *); void mousePressEvent(QMouseEvent *); void paintEvent(QPaintEvent *); signals: void signalLabelPress(PixLabel *); private: void initVariable(); void initSetupUi(); void createFrame(); void createWidget(); void createLayout(); void paintWidget(int, QPainter *); bool getMouseEnterFlag(); bool getMousePressFlag(); bool m_mouseEnterFlag; bool m_mousePressFlag; QHBoxLayout *m_pHLayout; QLabel *m_pLabelIcon; QLabel *m_pLabelText; }; #endif // SLIDERPICTURE_H(2)sliderpicture.cpp
#include "sliderpicture.h" SliderPicture::SliderPicture(QWidget *parent) : QWidget(parent) , mouse_press(false) , mouse_move(false) , label_move(true) , current_index(0) , current_pos_x(0) { setWindowFlags(Qt::FramelessWindowHint | Qt::Dialog); resize(680, 370); background_label = new QLabel(this); background_label->setPixmap(QPixmap(":/bg_bottom")); background_label->setGeometry(QRect(0, 0, this->width(), this->height())); QPixmap pixmap(QSize(this->width()*4, this->height())); QPainter painter(&pixmap); for(int i = 0; i < 4; i++){ painter.drawImage(QRect(this->width()*i, 0, this->width(), this->height()), QImage(QString(":/desktop_%1").arg(i))); } total_label = new QLabel(this); total_label->resize(pixmap.size()); total_label->setPixmap(pixmap); total_label->move(0, 0); for(int index = 0; index < 4; index++) { PixLabel *label = new PixLabel(this); label->resize(QSize(155, 45)); label->setPixmap(QPixmap(QString(":/btn_%1").arg(index))); if (index == 0) { label->setText(tr("function")); } else if (index == 1) { label->setText(tr("clearcookie")); } else if (index == 2) { label->setText(tr("triggerman")); } else { label->setText(tr("booster")); } label->move(8+index*170, 319); connect(label, SIGNAL(signalLabelPress(PixLabel*)), this, SLOT(changeCurrentPage(PixLabel*))); label_array.append(label); } label_array.first()->setMousePressFlag(true); label_array.first()->setFocus(); close_button = new PushButton(this); close_button->setPicName(":/close"); close_button->move(this->width()-close_button->width(), 0); close_button->setToolTip(tr("close")); connect(close_button, SIGNAL(clicked()), this, SLOT(close())); } SliderPicture::~SliderPicture() { } void SliderPicture::mousePressEvent(QMouseEvent *event) { if(event->button() == Qt::LeftButton) { m_mouseSrcPos = event->pos(); if(m_mouseSrcPos.y() <= 40) { mouse_move = true; } else { current_pos_x = total_label->x(); mouse_press = true; } } else if(event->button() == Qt::RightButton) { if(label_move) { if(current_index > 0) { current_index--; moveCurrentPage(false); //move right } } } } void SliderPicture::mouseReleaseEvent(QMouseEvent *event) { int xpos = 0; if (mouse_press) { if (label_move) { m_mouseDstPos = event->pos(); xpos = m_mouseDstPos.x() - m_mouseSrcPos.x(); if (xpos > 0) { //the plan is:move right if(xpos >= 150) { //mouse gap if(current_index > 0) { //move right current_index--; moveCurrentPage(false); } else { moveCurrentPage(true); //move left } } else { moveCurrentPage(true); //move left } } else { //the plan is:move right if(xpos <= -150) { if(current_index < 4-1) { current_index++; moveCurrentPage(true); //move left } else { moveCurrentPage(false); //move right } } else { moveCurrentPage(false); //move right } } } mouse_press = false; } else if(mouse_move){ mouse_move = false; } } void SliderPicture::mouseMoveEvent(QMouseEvent *event) { int xPos = 0; if(mouse_press) { if(label_move) { m_mouseDstPos = event->pos(); xPos = m_mouseDstPos.x() - m_mouseSrcPos.x(); setLabelMove(false); total_label->move(current_pos_x + xPos, 0); setLabelMove(true); } } else if(mouse_move) { m_mouseDstPos = event->pos(); this->move(this->pos() + m_mouseDstPos - m_mouseSrcPos); } } void SliderPicture::keyPressEvent(QKeyEvent *event) { if(label_move) { switch(event->key()) { case Qt::Key_Left: case Qt::Key_Up: if(current_index > 0) { current_index--; moveCurrentPage(false); //move right } break; case Qt::Key_Right: case Qt::Key_Down: if(current_index < 4-1) { current_index++; moveCurrentPage(true); //move left } break; default: break; } } } void SliderPicture::moveCurrentPage(bool direction) { //change all label for(int i=0; i<4; i++) { if(i != current_index) { label_array.at(i)->setMousePressFlag(false); } else{ label_array.at(i)->setMousePressFlag(true); } } //split point of picture //0-680 680-1360 1360-2040 2040-2720 //true:left false:right //index=0, move -680*0 //index=1, move -680*1 //index=2, move-680*2 //index=3, move-680*3 setLabelMove(false); int current_pos_x = total_label->x(); //label position int dest_pos_x = -680 * current_index; if(direction) { while(current_pos_x > dest_pos_x) { total_label->move(current_pos_x-20, 0); current_pos_x = total_label->x(); qApp->processEvents(QEventLoop::AllEvents); } } else { while(current_pos_x < dest_pos_x) { total_label->move(current_pos_x+20, 0); current_pos_x = total_label->x(); qApp->processEvents(QEventLoop::AllEvents); } } total_label->move(dest_pos_x, 0); setLabelMove(true); } void SliderPicture::setLabelMove(bool enable) { label_move = enable; } void SliderPicture::changeCurrentPage(PixLabel *label) { int index = 0; for(int iter = 0; iter < 4; iter++) { if(label != label_array.at(iter)) { label_array.at(iter)->setMousePressFlag(false); } else { index = iter; //get the clicked label of index } } if(index < current_index) { //move left while(index != current_index) { current_index--; moveCurrentPage(false); } } else if(index > current_index) { //move right while(index != current_index) { current_index++; moveCurrentPage(true); } } } /************PushButton**************/ PushButton::PushButton(QWidget *parent) : QPushButton(parent) { status = NORMAL; mouse_press = false; } PushButton::~PushButton() { } void PushButton::setPicName(QString pic_name) { this->pic_name = pic_name; setFixedSize(QPixmap(pic_name).size()); } void PushButton::enterEvent(QEvent *) { status = ENTER; update(); } void PushButton::mousePressEvent(QMouseEvent *event) { if(event->button() == Qt::LeftButton) { mouse_press = true; status = PRESS; update(); } } void PushButton::mouseReleaseEvent(QMouseEvent *event) { if(mouse_press && this->rect().contains(event->pos())) { mouse_press = false; status = ENTER; update(); emit clicked(); } } void PushButton::leaveEvent(QEvent *) { status = NORMAL; update(); } void PushButton::paintEvent(QPaintEvent *) { QPainter painter(this); QPixmap pixmap; switch(status) { case NORMAL: { pixmap.load(pic_name); break; } case ENTER: { pixmap.load(pic_name + QString("_hover")); break; } case PRESS: { pixmap.load(pic_name + QString("_pressed")); break; } case NOSTATUS: { pixmap.load(pic_name); break; } default: pixmap.load(pic_name); } painter.drawPixmap(rect(), pixmap); } /************PixLabel**************/ PixLabel::PixLabel(QWidget *parent) : QWidget(parent) { initVariable(); initSetupUi(); } PixLabel::~PixLabel() { delete m_pLabelIcon; delete m_pLabelText; delete m_pHLayout; } void PixLabel::setPixmap(const QPixmap &pixmap) { m_pLabelIcon->setPixmap(pixmap.scaled(QSize(30, 30), Qt::KeepAspectRatio, Qt::SmoothTransformation)); } void PixLabel::setText(const QString &text) { m_pLabelText->setText(text); } void PixLabel::setMouseEnterFlag(bool flag) { m_mouseEnterFlag = flag; this->update(); } void PixLabel::setMousePressFlag(bool flag) { m_mousePressFlag = flag; this->update(); } void PixLabel::enterEvent(QEvent *) { if(!getMousePressFlag()) { setMouseEnterFlag(true); } this->setCursor(Qt::PointingHandCursor); } void PixLabel::leaveEvent(QEvent *) { setMouseEnterFlag(false); } void PixLabel::mousePressEvent(QMouseEvent *e) { if(e->button() == Qt::LeftButton) { setMousePressFlag(true); emit signalLabelPress(this); } } void PixLabel::paintEvent(QPaintEvent *e) { QPainter painter(this); if(getMouseEnterFlag()) { paintWidget(50, &painter); } else if(getMousePressFlag()) { paintWidget(80, &painter); } QWidget::paintEvent(e); } void PixLabel::initVariable() { setMouseEnterFlag(false); setMousePressFlag(false); } void PixLabel::initSetupUi() { createFrame(); createWidget(); createLayout(); } void PixLabel::createFrame() { this->setStyleSheet("QWidget{background:transparent;border:0px;color:white;font-weight:bold;font-size:16px;}"); } void PixLabel::createWidget() { m_pLabelIcon = new QLabel(this); m_pLabelText = new QLabel(this); } void PixLabel::createLayout() { m_pHLayout = new QHBoxLayout; m_pHLayout->setSpacing(10); m_pHLayout->setContentsMargins(QMargins(5, 0, 5, 0)); m_pHLayout->addWidget(m_pLabelIcon); m_pHLayout->addWidget(m_pLabelText); m_pHLayout->addStretch(); this->setLayout(m_pHLayout); } void PixLabel::paintWidget(int transparency, QPainter *device) { QPen pen(Qt::NoBrush, 1); device->setPen(pen); QLinearGradient linear(this->rect().topLeft(), this->rect().bottomLeft()); linear.setColorAt(0, QColor(255, 255, 255, transparency)); QBrush brush(linear); device->setBrush(brush); device->drawRoundedRect(this->rect(), 2, 2); } inline bool PixLabel::getMouseEnterFlag() { return m_mouseEnterFlag; } inline bool PixLabel::getMousePressFlag() { return m_mousePressFlag; }(3)main.cpp
#include "sliderpicture.h" #include <QApplication> #include <QTranslator> int main(int argc, char *argv[]) { QApplication a(argc, argv); QTranslator translator; translator.load("sliderpicture.qm",":/"); a.installTranslator(&translator); SliderPicture w; w.show(); return a.exec(); }
运行部分效果图(可以通过鼠标滑动或通过键盘方向键控制或者点击下方按钮):
2、代码二:按钮滑动(QGraphicsItem)
(1)parallaxhome.h#ifndef PARALLAXHOME #define PARALLAXHOME #include <QtCore> #include <QtGui> #include <QtSvg> class NaviBar : public QObject, public QGraphicsRectItem { Q_OBJECT public: NaviBar(QGraphicsItem *parent = 0); void setPageOffset(qreal ofs); QRectF rect() const; signals: void pageSelected(int page); protected: void mousePressEvent(QGraphicsSceneMouseEvent *event); void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0); private: QList<QGraphicsSvgItem *> m_icons; QGraphicsRectItem *m_cursor; }; class ParallaxHome: public QGraphicsView { Q_OBJECT public: ParallaxHome(QWidget *parent = 0); private: QGraphicsScene m_scene; NaviBar *m_naviBar; QGraphicsPixmapItem *m_wallpaper; QTimeLine m_pageAnimator; qreal m_pageOffset; QList<QGraphicsPixmapItem*> m_items; QList<QPointF> m_positions; bool mouse_move; QPoint m_mouseSrcPos; QPoint m_mouseDstPos; signals: void pageChanged(int page); public slots: void slideRight(); void slideLeft(); void slideBy(int dx); void choosePage(int page); private slots: void shiftPage(int frame); protected: void resizeEvent(QResizeEvent *event); void keyPressEvent(QKeyEvent *event); void mousePressEvent(QMouseEvent *event); void mouseReleaseEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event); void leaveEvent ( QEvent *event); void enterEvent(QEvent *event); private: void layoutScene(); void setupScene(); }; #endif // PARALLAXHOME(2)parallaxhome.cpp
#include "parallaxhome.h" #define PAGE_COUNT 5 #define ICON_SIZE 50 #define ICON_PAD 4 NaviBar::NaviBar(QGraphicsItem *parent) : QGraphicsRectItem(parent) { setAcceptHoverEvents(true); setRect(0, 0, 5 * ICON_SIZE, ICON_SIZE); setPen(Qt::NoPen); QStringList names; names << "map" << "web" << "home" << "weather" << "contacts"; for (int i = 0; i < names.count(); ++i) { QString fname = names[i]; fname.prepend(":/icons/"); fname.append("-page.svg"); QGraphicsSvgItem *icon = new QGraphicsSvgItem(fname); icon->setParentItem(this); icon->setCursor(Qt::PointingHandCursor); const int dim = ICON_SIZE - ICON_PAD * 2; qreal sw = dim / icon->boundingRect().width(); qreal sh = dim / icon->boundingRect().height(); icon->setTransform(QTransform().scale(sw, sh)); icon->setZValue(2); m_icons << icon; } m_cursor = new QGraphicsRectItem; m_cursor->setParentItem(this); m_cursor->setRect(0, 0, ICON_SIZE, ICON_SIZE); m_cursor->setZValue(1); m_cursor->setPen(Qt::NoPen); m_cursor->setBrush(QColor(Qt::white)); m_cursor->setOpacity(0.6); } void NaviBar::setPageOffset(qreal ofs) { m_cursor->setPos(ofs * ICON_SIZE, 0); for (int i = 0; i < m_icons.count(); ++i) { int y = (i == static_cast<int>(ofs + 0.5)) ? ICON_PAD : ICON_PAD * 2; m_icons[i]->setPos(i * ICON_SIZE + ICON_PAD, y); m_icons[i]->setOpacity(1); } } QRectF NaviBar::rect() const { return QRectF(0, 0, 250, 50); } void NaviBar::mousePressEvent(QGraphicsSceneMouseEvent *event) { if (this->boundingRect().contains(event->pos())) { emit pageSelected(static_cast<int>(event->pos().x() / ICON_SIZE)); } } void NaviBar::paint(QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { painter->setBrush(Qt::white); painter->setOpacity(0.2); painter->drawRect(option->rect); //painter->drawRect(option->rect.adjusted(-20, ICON_PAD, 20, 0)); } ParallaxHome::ParallaxHome(QWidget *parent) : QGraphicsView(parent) , m_pageOffset(-2) , mouse_move(false) { resize(360, 504); setWindowFlags(Qt::FramelessWindowHint); setupScene(); setScene(&m_scene); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setFrameShape(QFrame::NoFrame); setWindowTitle("Parallax Home"); connect(&m_pageAnimator, SIGNAL(frameChanged(int)), SLOT(shiftPage(int))); m_pageAnimator.setDuration(500); m_pageAnimator.setFrameRange(0, 100); m_pageAnimator.setCurveShape(QTimeLine::EaseInCurve); pageChanged(static_cast<int>(m_pageOffset)); move((QApplication::desktop()->width() - width())/2, (QApplication::desktop()->height() - height())/2); } void ParallaxHome::slideRight() { if (m_pageAnimator.state() != QTimeLine::NotRunning) return; int edge = -(m_pageOffset - 1); if (edge < PAGE_COUNT) slideBy(-1); } void ParallaxHome::slideLeft() { if (m_pageAnimator.state() != QTimeLine::NotRunning) return; if (m_pageOffset < 0) slideBy(1); } void ParallaxHome::slideBy(int dx) { int start = m_pageOffset * 1000; int end = (m_pageOffset + dx) * 1000; m_pageAnimator.setFrameRange(start, end); m_pageAnimator.start(); } void ParallaxHome::choosePage(int page) { if (m_pageAnimator.state() != QTimeLine::NotRunning) return; if (static_cast<int>(-m_pageOffset) == page) return; slideBy(-page - m_pageOffset); } void ParallaxHome::shiftPage(int frame) { int ww = width(); int hh = height() - m_naviBar->rect().height(); int oldPage = static_cast<int>(-m_pageOffset); m_pageOffset = static_cast<qreal>(frame) / qreal(1000); int newPage = static_cast<int>(-m_pageOffset); m_naviBar->setPageOffset(-m_pageOffset); if (oldPage != newPage) emit pageChanged(newPage); int ofs = m_pageOffset * ww; for (int i = 0; i < m_items.count(); ++i) { QPointF pos = m_positions[i]; QPointF xy(pos.x() * ww, pos.y() * hh); m_items[i]->setPos(xy + QPointF(ofs, 0)); } int center = m_wallpaper->pixmap().width() / 2; const int parallax = 3; int base = center - (ww / 2) - (PAGE_COUNT >> 1) * (ww / parallax); int wofs = base - m_pageOffset * ww / parallax; m_wallpaper->setPos(-wofs, 0); } void ParallaxHome::resizeEvent(QResizeEvent *event) { Q_UNUSED(event); layoutScene(); } void ParallaxHome::keyPressEvent(QKeyEvent *event) { if (event->key() == Qt::Key_Right) slideRight(); else if (event->key() == Qt::Key_Left) slideLeft(); event->accept(); } void ParallaxHome::mousePressEvent(QMouseEvent *event) { if(event->button() == Qt::LeftButton) { m_mouseSrcPos = event->pos(); if(m_mouseSrcPos.y() <= 40) { mouse_move = true; } } QGraphicsView::mousePressEvent(event); } void ParallaxHome::mouseReleaseEvent(QMouseEvent *event) { if(mouse_move){ mouse_move = false; } QGraphicsView::mouseReleaseEvent(event); } void ParallaxHome::mouseMoveEvent(QMouseEvent *event) { if(mouse_move) { m_mouseDstPos = event->pos(); this->move(this->pos() + m_mouseDstPos - m_mouseSrcPos); } QGraphicsView::mouseMoveEvent(event); } void ParallaxHome::leaveEvent(QEvent *event) { } void ParallaxHome::enterEvent(QEvent *event) { } void ParallaxHome::layoutScene() { int ww = width(); int hh = height(); m_scene.setSceneRect(0, 0, PAGE_COUNT * ww - 1, hh - 1); centerOn(ww / 2, hh / 2); int nw = m_naviBar->rect().width(); int nh = m_naviBar->rect().height(); m_naviBar->setPos((ww - nw) / 2, hh - nh); shiftPage(m_pageOffset * 1000); } void ParallaxHome::setupScene() { qsrand(QTime::currentTime().second()); QStringList names; names << "brownies" << "cookies" << "mussels" << "pizza" << "sushi"; names << "chocolate" << "fish" << "pasta" << "puding" << "trouts"; for (int i = 0; i < PAGE_COUNT * 2; ++i) { QString fname = names[i]; fname.prepend(":/images/"); fname.append(".jpg"); QPixmap pixmap(fname); pixmap = pixmap.scaledToWidth(200); QGraphicsPixmapItem *item = m_scene.addPixmap(pixmap); m_items << item; qreal x = (i >> 1) + (qrand() % 30) / 100.0; qreal y = (i & 1) / 2.0 + (qrand() % 20) / 100.0; m_positions << QPointF(x, y); item->setZValue(1); } m_naviBar = new NaviBar; m_scene.addItem(m_naviBar); m_naviBar->setZValue(2); connect(m_naviBar, SIGNAL(pageSelected(int)), SLOT(choosePage(int))); m_wallpaper = m_scene.addPixmap(QPixmap(":/icons/surfacing.png")); m_wallpaper->setZValue(0); //m_scene.setItemIndexMethod(QGraphicsScene::NoIndex); QPushButton *close_button = new QPushButton(this); close_button->resize(27, 22); close_button->setFocusPolicy(Qt::NoFocus); 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);}"); close_button->setCursor(Qt::PointingHandCursor); close_button->raise(); close_button->move(this->width()-close_button->width(), 0); close_button->setToolTip(tr("close")); connect(close_button, SIGNAL(clicked()), this, SLOT(close())); }(3)main.cpp
#include "parallaxhome.h" int main(int argc, char *argv[]) { QApplication app(argc, argv); ParallaxHome w; w.show(); return app.exec(); }
运行效果图:
三、总结
(1)代码可以应用到相应的项目中,但相应功能还需要自定义开发。(2)此源码已经打包上传到csdn上可登录下载(http://download.csdn.net/detail/taiyang1987912/8674131)。
(3)若有建议,请留言,在此先感谢!
相关文章推荐
- Qt浅谈之二十六图片滑动效果
- Qt之实现图片滑动效果
- Slick 图片左右滑动幻灯片效果
- flash特效原理:图片滑动放大效果(3)
- JavaScript 图片滑动切换效果
- android Gallery组件实现的iPhone图片滑动效果实例
- 淘宝首页 图片滑动切换效果 基于CSS3的transition方法实现
- jq实现左侧显示图片右侧文字滑动切换效果
- 浅谈CSS和JQuery实现鼠标悬浮图片放大效果
- 自定义TabHost实现背景图片随选项卡切换滑动效果
- zepto.js手机端网页上下手指滑动图片切换效果代码
- 门户网常用的文字滑动使图片切换效果
- android 自定义ImageView实现图片手势滑动,多点触摸放大缩小效果
- 实现图片滑动、滚动、菜单栏(导航)滑动、文字滚动等效果的网页插件superslide2
- Android 自定义 HorizontalScrollView 打造再多图片(控件)也不怕 OOM 的横向滑动效果
- QT 滑动效果之 Qt动画组的简单使用(一)
- jQuery实现的Tab滑动选项卡及图片切换(多种效果)小结
- Android实现局部图片滑动指引效果
- JQuery.HoverDir库基本使用方法,实现图片滑动动画效果
- 实现广告图片循环轮播效果(包括实现手动滑动循环)