当前位置:   article > 正文

Qt 实现类似于手机界面的切换效果_qt 类似手机的返回键

qt 类似手机的返回键

Qt 实现类似于手机界面的切换效果

效果:
请添加图片描述

实现思路:
主要利用QStackedWidget, 将要切换的界面添加到其中,并移除上一个界面,实现界面的灵活切换。
QPropertyAnimation实现两个界面切换的动画过渡效果,最后通过event函数监听退回按键,切换到之前的界面。继承QPushButton, 可以自由添加多个要切换的页面。

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QWidget>
#include <QEvent>
#include <QKeyEvent>
#include <QMainWindow>
#include <QStackedWidget>
#include <QCoreApplication>
#include <QPropertyAnimation>
#include <QParallelAnimationGroup>

#include "mylayout.h"
#include "switchbutton.h"
#include "../filetransfer/filetransfer.h"
#include "../serverm/serverm.h"

class MainWindow : public QMainWindow
{
    Q_OBJECT
public:

    typedef enum{
        MainWindowPage = 0,
        FileWidgetPage,
        ServerMPage
    }PageIndex;

    static MainWindow* getInstance();
    ~MainWindow() = default;
    int getCurrentPageIndex() { return m_stackWidget->currentIndex(); }

public slots:
    void onSwitchWidget(QWidget* widget);
    void onSwitchPage(int index);

protected slots:
    void onAnimationFinished();
    bool event(QEvent *event) override;


private:
    MainWindow(QWidget *parent = nullptr);
    static MainWindow* instance_;
    void init();

    QStackedWidget* m_stackWidget;
    QWidget* m_widget;
    MyLayout* m_layout;
    SwitchButton* m_fileTransfer;
    SwitchButton* m_serverM;

    int m_preIndex;     //上一个界面索引
    int m_pageIndex;    // 当前显示的界面

};
#endif // MAINWINDOW_H

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58

mainwindow.cpp

#include "mainwindow.h"
MainWindow* MainWindow::instance_ = nullptr;

MainWindow::MainWindow(QWidget *parent)
    :  QMainWindow(parent), m_preIndex(-1), m_pageIndex(MainWindowPage)
{
    init();
}

MainWindow* MainWindow::getInstance()
{
    if(!instance_)
        instance_ = new MainWindow;
    return instance_;
}

void MainWindow::init()
{
    m_widget = new QWidget;
    m_layout = new MyLayout;
    m_widget->setLayout(m_layout);

    m_fileTransfer = new SwitchButton("File Transfer", FileWidgetPage);
    connect(m_fileTransfer, SIGNAL(clicked(int)), this, SLOT(onSwitchPage(int)));

    m_serverM = new SwitchButton("Server Monitoring", ServerMPage);
    connect(m_serverM, SIGNAL(clicked(int)), this, SLOT(onSwitchPage(int)));

    m_layout->addWidget(m_fileTransfer);
    m_layout->addWidget(m_serverM);

    m_stackWidget = new QStackedWidget;
    setCentralWidget(m_stackWidget);
    m_stackWidget->insertWidget(MainWindowPage, m_widget);
}

void MainWindow::onSwitchWidget(QWidget* widget)
{
    // 确保当前界面在动画结束前不被隐藏
    m_preIndex = m_stackWidget->currentIndex();
    if(m_stackWidget->indexOf(widget) == -1)  // 部件不在stackwidget中则加入
        m_stackWidget->addWidget(widget);
    m_stackWidget->setCurrentWidget(widget);
    m_stackWidget->widget(m_preIndex)->show();

    // 前一个界面
    QPropertyAnimation *animation1 = new QPropertyAnimation(m_stackWidget->widget(m_preIndex), "geometry");
    animation1->setDuration(200);
    animation1->setStartValue(QRect(0, 0, this->width(), this->height()));
    animation1->setEndValue(QRect(-this->width(), 0, this->width(), this->height()));

    // 下一个界面
    QPropertyAnimation *animation2 = new QPropertyAnimation(widget, "geometry");
    animation2->setDuration(200);
    animation2->setStartValue(QRect(this->width(), 0, this->width(), this->height()));
    animation2->setEndValue(QRect(0, 0, this->width(), this->height()));

    QParallelAnimationGroup *group = new QParallelAnimationGroup;
    group->addAnimation(animation1);
    group->addAnimation(animation2);
    group->start();

    connect(group, SIGNAL(finished()), this, SLOT(onAnimationFinished()));

}

void MainWindow::onAnimationFinished()
{
    QWidget* preWidget = m_stackWidget->widget(m_preIndex);
    // 隐藏移除的画面
    if(m_preIndex > 0){
        m_stackWidget->removeWidget(preWidget);
    }
}

bool MainWindow::event(QEvent *event)
{
    if(m_pageIndex != MainWindowPage)
        return QMainWindow::event(event);
    QEvent::Type t = event->type();
    switch(t)
    {
    case QEvent::KeyRelease:	// Key_F1 仅为了在PC端更方便的测试, Key_Back用于移动端
        if(((static_cast<QKeyEvent*>(event))->key() == Qt::Key_Back)
            || ((static_cast<QKeyEvent*>(event))->key() == Qt::Key_F1))
        {
            event->accept();
            int index = m_stackWidget->currentIndex();
            if(index == MainWindowPage){   // 主界面程序退出
                QCoreApplication::quit();
            }
            return true;
        }
        break;
    default:
        break;
    }
    return QMainWindow::event(event);
}

void MainWindow::onSwitchPage(int index)
{
    if(index == MainWindowPage){
        onSwitchWidget(m_widget);
    }
    else if(index == FileWidgetPage){
        onSwitchWidget(FileTransfer::getInstance());
    }
    else if(index == ServerMPage){
        onSwitchWidget(ServerM::getInstance());
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112

switchButton.h

#ifndef MYBUTTON_H
#define MYBUTTON_H

#include <QPushButton>

class SwitchButton : public QPushButton
{
    Q_OBJECT
public:
    explicit SwitchButton(const QString &text, int index, QWidget* parent = nullptr);
    QSize sizeHint() const override;

signals:
    void clicked(int);

protected slots:
    void onClicked();

private:
    int index_;
};

#endif // MYBUTTON_H

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

switchButton.cpp

#include "switchbutton.h"

SwitchButton::SwitchButton(const QString &text, int index, QWidget* parent)
    : QPushButton(parent), index_(index)
{
    setText(text);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    connect(this, SIGNAL(clicked()), this, SLOT(onClicked()));
}

void SwitchButton::onClicked()
{
    emit clicked(index_);
}

QSize SwitchButton::sizeHint() const
{
    QSize size = QPushButton::sizeHint();
    size.setHeight(size.width());
    return size;
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

在你要切换的部件中添加以下代码即可

bool FileTransfer::event(QEvent *event)
{
    if(MainWindow::getInstance()->getCurrentPageIndex() != MainWindow::FileWidgetPage)
        return QWidget::event(event);
    QEvent::Type t = event->type();
    switch(t)
    {
    case QEvent::KeyRelease:
        if(((static_cast<QKeyEvent*>(event))->key() == Qt::Key_Back)
            || ((static_cast<QKeyEvent*>(event))->key() == Qt::Key_F1))
        {
            event->accept();
            int cur_index = stackWidget_->currentIndex();
            if(cur_index <= 0){   // 返回主界面
//                MainWindow::getInstance()->onSwitchWidget(MainWindow::getInstance()->getMainWidget());
                MainWindow::getInstance()->onSwitchPage(MainWindow::MainWindowPage);
            }
            else {    // 其他界面返回
                onSwitchWidget(stackWidget_->widget(--cur_index));
            }
            return true;
        }
        break;
    default:
        break;
    }
    return QWidget::event(event);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/81518
推荐阅读
相关标签
  

闽ICP备14008679号