赞
踩
效果:
实现思路:
主要利用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
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()); } }
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
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; }
在你要切换的部件中添加以下代码即可
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); }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。