在上章我们学习了63.QT-重写QStackedWidget模仿iphone的home界面,实现左右滑动_诺谦的博客-CSDN博客,但是该界面是实现的上下滑动效果,如果想模拟手机home滑动界面,则需要实现左右滑动效果.

本章,则重写QStackedWidget类,来真正的模拟手机,来实现home界面左右滑动效果.

1.SmoothStackedWidget类实现

demo界面如下图所示(创建了4个子界面):

效果图如下所示(支持快滑,慢滑):

如果是慢滑,则根据当前滑到的界面处于哪一页占比更多,则就跳到哪里.

否则就是快滑,根据滑动的偏移值来决定跳转

同样也支持边缘滑动检测(已在最边缘时,则滑动速率减慢,告诉用户已到边缘):

demo下载:qt实现QStackedWidget界面左右滑动示例_qt如何实现长图滑动-嵌入式文档类资源-CSDN下载

若没有积分,可以进Qt | QML | C++技术交流群760631646(1群) 693036968(2群)免费获取文章资源.

2.代码实现

头文件如下所示:

#ifndef SMOOTHSTACKEDWIDGET_H
#define SMOOTHSTACKEDWIDGET_H#include <QObject>
#include <QWidget>
#include <QStackedWidget>
#include <QAbstractScrollArea>
#include <QPixmap>
#include <QPropertyAnimation>class SmoothStackedWidget : public QStackedWidget
{Q_OBJECT#define SMOOTH_MAX_MS   900                   //平滑滑动时的最大延迟时间
#define SMOOTH_EDGE_MOVE_RATIO   0.14         //边缘移动系数,范围0~1,越低越慢typedef enum tagScrollMouseDragInfo {MOUSE_RELEASE = 0,                       //鼠标离开MOUSE_PRESS = 1,                         //按下MOUSE_PRESS_MOVE = 2,                    //按下移动MOUSE_RELEASE_MOVE = 3                   //鼠标离开并滑动}Scroll_Mouse_Drag_INFO_E;typedef enum tagSmoothAnimationSwitchInfo {SWITCH_PRE = -1,                      //切换上一页SWITCH_NONE = 0,                      //不切换SWITCH_NEXT = 1,                      //切换下一页}AnimationSwitch_Drag_INFO_E;Scroll_Mouse_Drag_INFO_E m_dragFlag = MOUSE_RELEASE;AnimationSwitch_Drag_INFO_E m_switchFlag = SWITCH_NONE;QWidget *m_parent;QWidget m_smoothWidget;int m_smoothCurrentIndex=-1;QPropertyAnimation *animation;float m_smoothMovePos;bool eventFilter(QObject *obj, QEvent *evt) override;void paintEvent(QPaintEvent *event) override;void resizeEvent(QResizeEvent *event) override;void SmoothLoadPixmap(bool isSmoothUpdate = false);void SmoothStartMove();void SmoothMove(int offset);void SmoothAnimationStart(int startPos, int endPos, int durationMs);void SmoothAnimationInit();public:explicit SmoothStackedWidget(QWidget *parent = nullptr);int addWidget(QAbstractScrollArea *w);int addWidget(QWidget *w);void setCurrentIndex(int index);void removeWidget(QWidget *w);void IconUpdate();      //刷新页数标签void UpdateSmooth();signals:protected slots:void OnSmoothAnimationFinished();};#endif // SMOOTHSTACKEDWIDGET_H

其中eventFilter()函数如下所示:

当鼠标(手指)按下移动时,则调用SmoothMove(offset),通过offset来动态显示滑动的界面.

当鼠标(手指)松开后,则调用SmoothAnimationStart()来实现界面移动(到底是切换上一页、还是切换下一页、还是当前页).

bool SmoothStackedWidget::eventFilter(QObject *obj, QEvent *evt)
{QMouseEvent *mouse =  dynamic_cast<QMouseEvent *>(evt);QWidget *w =  dynamic_cast<QWidget *>(obj);static int pressPoint_x   = 0;          //按下的坐标static int dragPoint_x    = -1;         //拖动时的坐标static qint64 pressMSec ;if(mouse && w && animation->state() == QAbstractAnimation::Stopped){if( mouse->type() ==QEvent::MouseButtonPress)    //首次按下{pressMSec = QDateTime::currentDateTime().toMSecsSinceEpoch();     //记录按下的时间dragPoint_x  = mouse->pos().x();               //当前坐标pressPoint_x = dragPoint_x;                    //按下的位置m_dragFlag = MOUSE_PRESS;}else if(mouse->type() == QEvent::MouseButtonRelease &&m_dragFlag == MOUSE_PRESS)               //未移动{m_dragFlag = MOUSE_RELEASE;}else if(mouse->type() == QEvent::MouseMove &&m_dragFlag == MOUSE_PRESS)               //初次滑动,判断移动阀值,避免误操作{if(qAbs(dragPoint_x - mouse->pos().x()) > 3)     //判断移动阀值,避免误操作{dragPoint_x = mouse->pos().x();SmoothStartMove();m_dragFlag = MOUSE_PRESS_MOVE;}}else if(mouse->type() == QEvent::MouseMove &&m_dragFlag== MOUSE_PRESS_MOVE )             //正在滑动{int offset = ( mouse->pos().x() - dragPoint_x);SmoothMove(offset);dragPoint_x = mouse->pos().x();}else if(mouse->type() == QEvent::MouseButtonRelease &&m_dragFlag == MOUSE_PRESS_MOVE)               //滑动结束,启动平滑滑动{int durationMs= QDateTime::currentDateTime().toMSecsSinceEpoch()-pressMSec;SmoothAnimationStart(pressPoint_x,mouse->pos().x(),durationMs);m_dragFlag = MOUSE_RELEASE;}}return QWidget::eventFilter(obj,evt);
}

SmoothAnimationStart()函数如下所示:

void  SmoothStackedWidget::SmoothAnimationStart(int startPos, int endPos, int durationMs)
{int pixelPerSecond=qAbs(endPos - startPos)*1000/durationMs;       //计算每秒像素点m_switchFlag = SWITCH_NONE;int moveX = qAbs(m_smoothWidget.x());float temp = width()*0.5;int animationEndX;//慢速滑动(速度过慢||时间过长),则根据当前滑到哪里,就跳到哪里if(pixelPerSecond<300 || durationMs > 1000) {if(moveX < (temp)) {        //[0,width/2] = 上一页if(currentIndex()==0) {animationEndX = -width();} else {animationEndX = 0;m_switchFlag = SWITCH_PRE;}} else if(moveX < (temp*3)) {    //[width/2,width*3/2] = 当前一页animationEndX = -width();} else {if(currentIndex()==(count()-1)) {   //[width*3/2,width*2] = 下一页animationEndX = -width();} else {animationEndX = -width()*2;m_switchFlag = SWITCH_NEXT;}}} else {    // 否则就是快速滑动if(startPos < endPos) { //向右滑动if(currentIndex()==0) {animationEndX = -width();} else {animationEndX = 0;m_switchFlag = SWITCH_PRE;}} else {         //向左滑动if(currentIndex()==(count()-1)) {animationEndX = -width();} else {animationEndX = -width()*2;m_switchFlag = SWITCH_NEXT;}}}//根据每秒滑动像素点,来计算滑动时长.int animationDuration = durationMs;float xOffsetRatio = qAbs(animationEndX - m_smoothWidget.x()) / (static_cast<float>(width())); //计算滑动占整屏比例if(animationDuration > (SMOOTH_MAX_MS * xOffsetRatio)) //滑动时间过大,则重置animationDuration = SMOOTH_MAX_MS * xOffsetRatio;animation->setDuration(animationDuration);animation->setStartValue(m_smoothWidget.geometry());animation->setEndValue(QRect(animationEndX, m_smoothWidget.y(), m_smoothWidget.width(), m_smoothWidget.height()));animation->start();
}

63.QT-重写QStackedWidget模仿iphone的home界面,实现左右滑动相关推荐

  1. [转贴]Android研究院之模仿iPhone列表数据View刷新动画详解(十九)

    因为我本人很喜欢在不同的页面之间跳转时加点好玩的动画,今天无意间看到一个动画效果感觉不错,几种效果图如下:既然好玩就 写在博客中,直接说就是:该效果类似于iPhone中View的切换动画效果,今天就只 ...

  2. Android模仿iPhone View旋转刷新数据动画详解

    因为小马很喜欢在不同的页面之间跳转时加点好玩的动画,今天无意间看到一个动画效果感觉不错,几种效果图如下,既然好玩就写在博客中,直接说就是:该效果类似于iPhone中View的切换动画效果,今天就只介绍 ...

  3. Qt之模仿QQ主面板界面

    Qt之模仿QQ主面板界面 Qt之模仿QQ主面板界面 效果图 结尾 效果图 这里大家值得注意的是,QQ等级设置,已经列表展开搜索时的三角符的旋转效果 //QQMainWindow.cpp #includ ...

  4. android view.gone 动画,Android 模仿iPhone列表数据View刷新动画详解

    因为我本人很喜欢在不同的页面之间跳转时加点好玩的动画,今天无意间看到一个动画效果感觉不错,几种效果图如下:既然好玩就写在博客中,直接说就是:该效果类似于iPhone中View的切换动画效果,今天就只介 ...

  5. QT重写QPushButton的背景图片及填充

    QT重写QPushButton的背景图片及填充 刚学习完QT的基本使用,使用已知知识重写QPushButton类 刚学习完QT的基本使用,使用已知知识重写QPushButton类 因为要使用QT来实现 ...

  6. QML完全模仿飞书日程界面(二)日(一天)的部分

    QML完全模仿飞书日程界面(二)日(一天)的部分 上一期链接: QML 完全模拟飞书日程界面(一).以及最后实现的效果: 然后再贴一个本期要模仿的部分: 目录 QML完全模仿飞书日程界面(二)日(一天 ...

  7. MFC界面编程新思路--模仿MATLAB式的界面

    像下面的这个图片一样,做一个图像测量的软件,界面需要模仿MATLAB,以前老是新建一个对话框式的MFC应用程序,或者是一个SDI的应用程序,搞了一年,慢慢的也想到了一种新的思路,而且今天也做了一个De ...

  8. 微信小程序 模仿华为音乐 列表界面

    微信小程序 模仿华为音乐 列表界面 index.js var app=getApp(); var listDatas = require("../../data/data_list.js&q ...

  9. Qt主线程和工作线程更新界面问题

    Qt在运行时会开启一个主线程,如果没有开启工作线程的话,所有界面上的操作都是在主线程,包括更新界面或者处理数据等操作.大家都知道如果处理数据比较多的话,最好是在单独开启一个线程来处理数据,这样就不会影 ...

  10. 基于TCP,Socket编程,模仿腾讯QQ界面,使用Java开发的一款网络聊天工具。QQ_Chat

    代码下载地址 原博客地址 QQ_Chat 基于TCP,Socket编程,模仿腾讯QQ界面,使用Java开发的一款网络聊天工具. (内含报告) 工具: Eclipse.Navicat for MySQL ...

最新文章

  1. 【数据结构】拓扑排序
  2. Loj #3055. 「HNOI2019」JOJO
  3. [转]Ubuntu SCIM 输入法不能光标跟随的解决
  4. Java内部类及其实例化
  5. vilatile 深入理解java虚拟机_《深入理解Java虚拟机》笔记 第十二章 volatile变量
  6. Nodejs进阶:使用DiffieHellman密钥交换算法
  7. moco-globalsettings
  8. 插入排序最优_排序专题插入排序
  9. 大数据之HBase教程
  10. 通信原理及系统系列9—— 设计无码间串扰的通信系统(理想低通滤波器)
  11. C语言 求5分2分1分硬币
  12. 深度linux64位系统下载,深度 Deepin 15.9 操作系统下载
  13. js实现兼容的本地化存储方案
  14. 我做的小程序,昨天赚了 2.06 元广告费
  15. 高校青年教师应该怎么提高收入
  16. wps英文参考文献怎么对齐_wps英文参考文献怎么对齐_【论文攻略】排版技巧——如何用 Word 编辑参考文献......
  17. 什么是再生纤维素纤维
  18. 基于TextRank算法的单领域多文本摘要(英文摘要)
  19. 如何通过引用传递变量?
  20. [转] 找到一个与VR相关的博客

热门文章

  1. 用微软的云计算来远程管理自己的电脑
  2. 牛客输入输出(依图科技)
  3. SWUST OJ#480 Locker doors
  4. 计算机系统限制某个用户只允许,Win10系统如何设置某些用户只能运行指定应用程序...
  5. 青年同辈应该有大器晚成的心理准备,共勉
  6. 不是计算机布尔检索命令的是,在计算机信息检索中,用于组配检索词和限字检索范围的布尔逻辑运算符包括哪些?...
  7. 英语句子主干成分分析
  8. Week8 CSP模拟 T2 HRZ学英语
  9. 租房退租时,房东不退押金怎么办?
  10. Linux内核抢占机制(preempt)