Qt界面滑动切换
三雷科技 人气:0一、Qt实现界面滑动切换效果
效果如下图,滑动效果移动上下屏幕。
二、 设计思路
利用QStackWidget将页面存储起来,因为页面比较少,因此我直接将所有的页面存储在QStachWidget中,如果页面相对较多,可以使用使用使渲染的方式。
然后使用show函数同时展示两个页面的内容,这个很重要,如果使用setCurrentIndex只会展示一个界面,这样不会出现两个界面同时存在的情况。
使用QPropertyAnimation以及QParallelAnimationGroup来设置界面切换动画。
当页面左移动时,将原始界面移除屏幕到左边,将当前界面从右边移动至现在界面位置。
当页面右移动时,将原始界面移除屏幕到右边,将当前界面从左边移动至屏幕展示位置
三、主要函数讲解
QPropertyAnimation:动画类,如果仅控制一个界面的动画可以直接设置动画效果后,start函数启动动画效果。
QParallelAnimationGroup:动画组类,控制一组动画同时运行,我们这里控制了两个界面因此需要使用QParallelAnimationGroup来控制两个界面的动画。
QStackedWidget:用于存储多个界面,当界面需要展示的时候可以通过setCurrentIndex展示当前页面。
四、源代码解析
4、1 初始化界面
在QStatchWidget中添加多个界面。因为这是游戏界面初始化,每一页有25题,一共有515道题目,翻页的总数等int(515/25).
#define MAX_NUM 515 LevelMainWidget::LevelMainWidget(QWidget* parent) : QWidget(parent) , m_ptrStackWidget(new QStackedWidget(this)) , m_ptrLayoutMain(new QHBoxLayout) , m_ptrBtnPre(new QPushButton("上一个", this)) , m_ptrBtnNext(new QPushButton("下一个", this)) , m_bDonghua(false) { // 添加界面 for (int i = 0; i < 515; i += 25) { int start = i + 1; int end = i + 25; if (end > 515) { end = 515; } LevelWidget* lvlWidget = new LevelWidget(start, end); m_listLevelWidget.append(lvlWidget); m_ptrStackWidget->addWidget(lvlWidget); connect(lvlWidget, &LevelWidget::sigBtnClick, this, &LevelMainWidget::slotBtnLevel); } // 设置当前展示的界面索引。 m_ptrStackWidget->setCurrentIndex(0); // 添加上一页按钮 m_ptrLayoutMain->addWidget(m_ptrBtnPre); // 添加展示的界面 m_ptrLayoutMain->addWidget(m_ptrStackWidget); // 添加下一页按钮 m_ptrLayoutMain->addWidget(m_ptrBtnNext); setFixedSize(500, 500); setLayout(m_ptrLayoutMain); initConnect(); } void LevelMainWidget::initConnect() { connect(m_ptrBtnPre, SIGNAL(clicked()), this, SLOT(slotBtnPre())); connect(m_ptrBtnNext, SIGNAL(clicked()), this, SLOT(slotBtnNext())); }
4、2 上一页滑动效果
获取展示界面的宽度以及高度,下移动界面的时候需要使用。
m_bDonghua:记录当前是否在动画效果中,如果在动画效果中不进行翻页(如果不设置,在快速切换的时候会出现重影)
m_ptrStackWidget->setCurrentIndex(PreIndex); m_ptrStackWidget->widget(currentIndex)->show();
animation1:设置当前页(未切换前)面页面的动画效果,你可以看到startValue和endValue,是从原始屏幕位置移除屏幕外。
animation2:设置即将切换到界面的动画效果,你可以看到startValue和endValue,是从屏幕外位置移除屏幕正中间。
当界面的动画同时执行的时候就出现滑动效果。
void LevelMainWidget::slotBtnPre() { if (m_bDonghua) { return; } m_bDonghua = true; int currentIndex = m_ptrStackWidget->currentIndex(); int windowWidth = m_ptrStackWidget->widget(currentIndex)->width(); int windowHieght = m_ptrStackWidget->widget(currentIndex)->height(); int PreIndex = currentIndex - 1; if (currentIndex == 0) { return; } m_ptrStackWidget->setCurrentIndex(PreIndex); m_ptrStackWidget->widget(currentIndex)->show(); QPropertyAnimation* animation1; QPropertyAnimation* animation2; QParallelAnimationGroup* group = new QParallelAnimationGroup; animation1 = new QPropertyAnimation(m_ptrStackWidget->widget(currentIndex), "geometry"); animation1->setDuration(500); animation1->setStartValue(QRect(0, 0, windowWidth, windowHieght)); animation1->setEndValue(QRect(windowWidth, 0, windowWidth, windowHieght)); animation2 = new QPropertyAnimation(m_ptrStackWidget->widget(PreIndex), "geometry"); animation2->setDuration(500); animation2->setStartValue( QRect(-windowWidth, 0, windowWidth, windowHieght)); animation2->setEndValue(QRect(0, 0, windowWidth, windowHieght)); group->addAnimation(animation1); group->addAnimation(animation2); group->start(); group->setProperty( "widget", QVariant::fromValue(m_ptrStackWidget->widget(currentIndex))); connect(group, SIGNAL(finished()), this, SLOT(onAnimationFinished())); }
4、3 下一页滑动效果
获取展示界面的宽度以及高度,下移动界面的时候需要使用。
m_bDonghua:记录当前是否在动画效果中,如果在动画效果中不进行翻页(如果不设置,在快速切换的时候会出现重影)
m_ptrStackWidget->setCurrentIndex(NextIndex); m_ptrStackWidget->widget(currentIndex)->show();
animation1:设置当前页(未切换前)面页面的动画效果,你可以看到startValue和endValue,是从原始屏幕位置移除屏幕外。
animation2:设置即将切换到界面的动画效果,你可以看到startValue和endValue,是从屏幕外位置移除屏幕正中间。
当界面的动画同时执行的时候就出现滑动效果。
void LevelMainWidget::slotBtnNext() { if (m_bDonghua) { return; } m_bDonghua = true; int currentIndex = m_ptrStackWidget->currentIndex(); int windowWidth = m_ptrStackWidget->widget(currentIndex)->width(); int windowHieght = m_ptrStackWidget->widget(currentIndex)->height(); int NextIndex = currentIndex + 1; if (currentIndex >= m_ptrStackWidget->count()) { return; } m_ptrStackWidget->setCurrentIndex(NextIndex); m_ptrStackWidget->widget(currentIndex)->show(); QPropertyAnimation* animation1; QPropertyAnimation* animation2; QParallelAnimationGroup* group = new QParallelAnimationGroup; animation1 = new QPropertyAnimation(m_ptrStackWidget->widget(currentIndex), "geometry"); animation1->setDuration(500); animation1->setStartValue(QRect(0, 0, windowWidth, windowHieght)); animation1->setEndValue(QRect(-windowWidth, 0, windowWidth, windowHieght)); animation2 = new QPropertyAnimation(m_ptrStackWidget->widget(NextIndex), "geometry"); animation2->setDuration(500); animation2->setStartValue(QRect(windowWidth, 0, windowWidth, windowHieght)); animation2->setEndValue(QRect(0, 0, windowWidth, windowHieght)); group->addAnimation(animation1); group->addAnimation(animation2); group->start(); group->setProperty( "widget", QVariant::fromValue(m_ptrStackWidget->widget(currentIndex))); connect(group, SIGNAL(finished()), this, SLOT(onAnimationFinished())); }
4、4 动画结束处理
动画结束后需要将上一界面进行隐藏,在切换页面的时候已经将上一页面的指针保存发送过来了。
group->setProperty( "widget", QVariant::fromValue(m_ptrStackWidget->widget(currentIndex)));
因此在动画结束时,获取上一页面的指针,然后再修改其隐藏状态即可。
void LevelMainWidget::onAnimationFinished() { QParallelAnimationGroup* group = (QParallelAnimationGroup*)sender(); QWidget* widget = group->property("widget").value<QWidget*>(); if (nullptr != widget) { widget->hide(); } m_bDonghua = false; }
五、源码地址
源码地址: 啊渊 / QT博客案例
加载全部内容