目录
  • 一、Qt实现界面滑动切换效果
  • 二、 设计思路
  • 三、主要函数讲解
  • 四、源代码解析
    • 4、1 初始化界面
    • 4、2 上一页滑动效果
    • 4、3  下一页滑动效果
    • 4、4 动画结束处理
  • 五、源码地址 

    一、Qt实现界面滑动切换效果

    效果如下图,滑动效果移动上下屏幕。

    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博客案例

    声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。