63.QT-重写QStackedWidget模仿iphone的home界面,实现左右滑动
在上章我们学习了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界面,实现左右滑动相关推荐
- [转贴]Android研究院之模仿iPhone列表数据View刷新动画详解(十九)
因为我本人很喜欢在不同的页面之间跳转时加点好玩的动画,今天无意间看到一个动画效果感觉不错,几种效果图如下:既然好玩就 写在博客中,直接说就是:该效果类似于iPhone中View的切换动画效果,今天就只 ...
- Android模仿iPhone View旋转刷新数据动画详解
因为小马很喜欢在不同的页面之间跳转时加点好玩的动画,今天无意间看到一个动画效果感觉不错,几种效果图如下,既然好玩就写在博客中,直接说就是:该效果类似于iPhone中View的切换动画效果,今天就只介绍 ...
- Qt之模仿QQ主面板界面
Qt之模仿QQ主面板界面 Qt之模仿QQ主面板界面 效果图 结尾 效果图 这里大家值得注意的是,QQ等级设置,已经列表展开搜索时的三角符的旋转效果 //QQMainWindow.cpp #includ ...
- android view.gone 动画,Android 模仿iPhone列表数据View刷新动画详解
因为我本人很喜欢在不同的页面之间跳转时加点好玩的动画,今天无意间看到一个动画效果感觉不错,几种效果图如下:既然好玩就写在博客中,直接说就是:该效果类似于iPhone中View的切换动画效果,今天就只介 ...
- QT重写QPushButton的背景图片及填充
QT重写QPushButton的背景图片及填充 刚学习完QT的基本使用,使用已知知识重写QPushButton类 刚学习完QT的基本使用,使用已知知识重写QPushButton类 因为要使用QT来实现 ...
- QML完全模仿飞书日程界面(二)日(一天)的部分
QML完全模仿飞书日程界面(二)日(一天)的部分 上一期链接: QML 完全模拟飞书日程界面(一).以及最后实现的效果: 然后再贴一个本期要模仿的部分: 目录 QML完全模仿飞书日程界面(二)日(一天 ...
- MFC界面编程新思路--模仿MATLAB式的界面
像下面的这个图片一样,做一个图像测量的软件,界面需要模仿MATLAB,以前老是新建一个对话框式的MFC应用程序,或者是一个SDI的应用程序,搞了一年,慢慢的也想到了一种新的思路,而且今天也做了一个De ...
- 微信小程序 模仿华为音乐 列表界面
微信小程序 模仿华为音乐 列表界面 index.js var app=getApp(); var listDatas = require("../../data/data_list.js&q ...
- Qt主线程和工作线程更新界面问题
Qt在运行时会开启一个主线程,如果没有开启工作线程的话,所有界面上的操作都是在主线程,包括更新界面或者处理数据等操作.大家都知道如果处理数据比较多的话,最好是在单独开启一个线程来处理数据,这样就不会影 ...
- 基于TCP,Socket编程,模仿腾讯QQ界面,使用Java开发的一款网络聊天工具。QQ_Chat
代码下载地址 原博客地址 QQ_Chat 基于TCP,Socket编程,模仿腾讯QQ界面,使用Java开发的一款网络聊天工具. (内含报告) 工具: Eclipse.Navicat for MySQL ...
最新文章
- 【数据结构】拓扑排序
- Loj #3055. 「HNOI2019」JOJO
- [转]Ubuntu SCIM 输入法不能光标跟随的解决
- Java内部类及其实例化
- vilatile 深入理解java虚拟机_《深入理解Java虚拟机》笔记 第十二章 volatile变量
- Nodejs进阶:使用DiffieHellman密钥交换算法
- moco-globalsettings
- 插入排序最优_排序专题插入排序
- 大数据之HBase教程
- 通信原理及系统系列9—— 设计无码间串扰的通信系统(理想低通滤波器)
- C语言 求5分2分1分硬币
- 深度linux64位系统下载,深度 Deepin 15.9 操作系统下载
- js实现兼容的本地化存储方案
- 我做的小程序,昨天赚了 2.06 元广告费
- 高校青年教师应该怎么提高收入
- wps英文参考文献怎么对齐_wps英文参考文献怎么对齐_【论文攻略】排版技巧——如何用 Word 编辑参考文献......
- 什么是再生纤维素纤维
- 基于TextRank算法的单领域多文本摘要(英文摘要)
- 如何通过引用传递变量?
- [转] 找到一个与VR相关的博客
热门文章
- 用微软的云计算来远程管理自己的电脑
- 牛客输入输出(依图科技)
- SWUST OJ#480 Locker doors
- 计算机系统限制某个用户只允许,Win10系统如何设置某些用户只能运行指定应用程序...
- 青年同辈应该有大器晚成的心理准备,共勉
- 不是计算机布尔检索命令的是,在计算机信息检索中,用于组配检索词和限字检索范围的布尔逻辑运算符包括哪些?...
- 英语句子主干成分分析
- Week8 CSP模拟 T2 HRZ学英语
- 租房退租时,房东不退押金怎么办?
- Linux内核抢占机制(preempt)