pyqt5如何在同一个窗口下切换不同界面

标签: Python  mysql  python  pyqt

本文为浙江大学数据库系统课程lab5进行图书管理系统设计过程中的经验总结
——zju gehao

问题的提出和基本前提

网上找了半天也没发现什么靠谱的解答,自己捣鼓着花费了好几个小时,总算是发现了两种能用的方法,先假设一下使用的场景:现在窗口的右半部分有两个界面想要切换显示

我们主体窗口的控件为self.main_widget,网格布局为self.main_layout,分为左右两部分:

  • 布局的左半部分为self.left_widget,它的作用是导航栏(标签和按钮),因此有一个就足够了
  • 布局的右半部分是self.right_widget,我想通过点击不同的按钮让这个区域显示不同的界面,但由于一个Qwidget只能容纳一组layout的布局,因此怎么切换界面是一个很令人苦恼的问题

我总结出了两种思路:

首先前提是,必须要有2个(或者两个以上的界面),每一个界面我都用一个Qwidget来表示,这个Qwidget里面可以使用QGridlayout网格布局(或者其他布局)来存放各种各样不同的子控件,比如按钮、标签、文本框等

假设我已经准备好了self.right_widget1和self.right_widget2,整体布局、左侧布局和右侧两个界面的布局如下所示:

class MainUi(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        '''
        初始化整体布局
        '''
        self.resize(1000, 800)
        self.desktopWidth = QApplication.desktop().width()  # 获取当前桌面的宽
        self.desktopHeight = QApplication.desktop().height()  # 获取当前桌面的高

        self.main_widget = QWidget()  # 创建窗口主部件
        self.main_widget.setObjectName('main_widget')  # 对象命名
        self.main_layout = QGridLayout()  # 创建网格布局的对象
        self.main_widget.setLayout(self.main_layout)  # 将主部件设置为网格布局

        self.init_left()  # 初始化左侧空间
        self.init_right()  # 初始化右侧空间

        # 将初始化完成的左侧、右侧空间加入整体空间的网格布局
        self.main_layout.addWidget(self.left_widget, 0, 0, 1, 1)
        self.main_layout.addWidget(self.right_widget1, 0, 1, 1, 6)
        #self.main_layout.addWidget(self.right_widget2, 0, 1, 1, 6)
        self.setCentralWidget(self.main_widget)  # 设置窗口主部件
    
    def init_left(self):
        '''
        初始化左侧布局
        '''
        self.left_widget = QWidget()  # 创建左侧部件
        self.left_widget.setObjectName('left_widget')  # 左侧部件对象命名
        self.left_layout = QGridLayout()  # 创建网格布局对象
        self.left_widget.setLayout(self.left_layout)  # 将左侧部件设置为网格布局
      	# 接下来添加按钮控件等...,细节略  
        
    def init_right(self):
        '''
        初始化右侧布局
        '''
        self.right_widget1 = QWidget()  # 创建右侧界面1
        self.right_layout1 = QGridLayout()  # 创建网格布局对象1
        self.right_widget1.setLayout(self.right_layout1)  # 设置右侧界面1的布局为网格布局
        self.Button1 = QPushButton() # 加一个用来界面跳转的button1
        self.Button1.setText("进入界面2")
        self.right_layout1.addWidget(self.Button1)
        
        self.right_widget2 = QWidget()  # 创建右侧界面2
        self.right_layout2 = QGridLayout()  # 创建网格布局对象2
        self.right_widget2.setLayout(self.right_layout2)  # 设置右侧界面2的布局为网格布局
        self.Button2 = QPushButton() # 加一个用来界面跳转的button2
        self.Button2.setText("进入界面1")
        self.right_layout2.addWidget(self.Button2)
        
        # 把切换界面的button和两个跳转函数绑定
        self.Button1.clicked.connect(self.clicked_1)
        self.Button2.clicked.connect(self.clicked_2)

现在的目标就是如何实现两个按钮的跳转函数去实现右侧两个界面的跳转,有两种思路:

解决方法

第一种思路:

首先随便选择一个widget(比如self.right_widget1)放到一开始的显示界面上,也就是上面的这句话

self.main_layout.addWidget(self.right_widget1, 0, 1, 1, 6)

然后当我点击该界面上的按钮Button1时,我从self.main_layout中删去这个self.right_widget1界面,再把self.right_widget2界面创建好并添加到self.main_layout布局里去,此时main布局的右侧就从界面1变成了界面2;想要从界面2跳转回界面1也是同样的道理,就先删去界面2的widget,再创建好界面1的widget并加入总布局里即可

# import sip
def clicked_1(self):
    # 删除界面1
    self.main_layout.removeWidget(self.right_widget1)
    sip.delete(self.right_widget1)
    # 创建界面2
    self.right_widget2 = QWidget()  # 创建右侧界面2
    self.right_layout2 = QGridLayout()  # 创建网格布局对象2
    self.right_widget2.setLayout(self.right_layout2)  # 设置右侧界面2的布局为网格布局
    self.Button2 = QPushButton() # 加一个用来界面跳转的button2
    self.Button2.setText("进入界面1")
    self.right_layout2.addWidget(self.Button2)
    # 添加界面2到总布局里
    self.main_layout.addWidget(self.right_widget2, 0, 1, 1, 6)
    
def clicked_2(self):
    # 删除界面2
    self.main_layout.removeWidget(self.right_widget2)
    sip.delete(self.right_widget2)
    # 创建界面1
    self.right_widget1 = QWidget()  # 创建右侧界面1
    self.right_layout1 = QGridLayout()  # 创建网格布局对象1
    self.right_widget1.setLayout(self.right_layout1)  # 设置右侧界面2的布局为网格布局
    self.Button1 = QPushButton() # 加一个用来界面跳转的button1
    self.Button1.setText("进入界面2")
    self.right_layout1.addWidget(self.Button1)
    # 添加界面1到总布局里
    self.main_layout.addWidget(self.right_widget1, 0, 1, 1, 6)

注意光使用self.main_layout.removeWidget(self.right_widget)好像并不能把widget删除,还需要加一句sip.delete(self.right_widget)才行(需要import sip),这种方法有一种缺点,想必你也发现了,就是每次切换页面都要删除原先的界面并新建想要跳转的界面,可是我们一般情况下并不希望每次跳转都删除、创建不变的东西,那会耗费更多的资源,导致更慢的速度,我们更希望用不到它的时候把它隐藏起来,当需要的时候再显示出来,这就是方法二的思路

第二种思路:

我们把所有的界面同时放在main的布局里的同一个位置,并且每次隐藏其他界面,只显示其中的一个,当我们想要切换界面的时候,其实就只要把原先显示的界面隐藏,想要显示的界面显示出来即可

当然此时一开始的代码要改一下,以便所有的界面都同时添加到main的右侧布局里:

self.main_layout.addWidget(self.right_widget1, 0, 1, 1, 6)
self.main_layout.addWidget(self.right_widget2, 0, 1, 1, 6)

然后只需要两个函数:Qwidget.hide()和Qwidget.show()

def clicked_1(self):
    self.right_widget1.hide() # 隐藏界面1
    self.right_widget2.show() # 显示界面2

def clicked_2(self):
    self.right_widget2.hide() # 隐藏界面2
    self.right_widget1.show() # 显示界面1

圆满解决!

这里随便选两个界面展示一下效果:

  • 第一个界面
    在这里插入图片描述
  • 第二个界面
    在这里插入图片描述
版权声明:本文为weixin_44406200原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_44406200/article/details/105576852

智能推荐

PyQt5的简单登录界面切换

这个Demo中的界面切换通过PyQt5中按键槽函数响应界面close(),show()函数实现 运行结果:...

Pyqt5中QtabWidget 界面切换触发如何实现

文章目录 遇到的问题 解决方案 currentChanged() currentIndex() 代码 实验结果 失能 使能 遇到的问题 对于一个tabwiget来说:如下图所示: 我想实现选择不同界面,能够是触发一个函数,而执行一个操作,此处,我希望选择pgpower能够失能上面的manager panel , 如果选择watercool 就使能上面的manggeer panel 解决方案 cur...

Android5.0 转场动画 共享元素 实现不同页面的同一个View的切换效果

实现上图Activity切换效果需要注意两点: Fragment之间实现切换效果查看 1.两个页面的布局文件中的View都需要添加相同的transitionName; 2.在跳转逻辑中使用如下方法...

vue 切换tab实现多个不同的组件显示在同一个挂载点且不跳转路由

目录 切换tab实现多个不同的组件显示在同一个挂载点 1,先来看看我的文件结构 2,查看main.vue文件 切换tab实现多个不同的组件显示在同一个挂载点 1,先来看看我的文件结构 将页面布局单独封装一个组件的好处,功能划分清晰,也很方便实现让用户自定义主图和布局的功能。 2,查看main.vue文件 请注意看注释~ 欢迎来讨论学习呀 如果本文对你有帮助,或者你有更好的意见,希望留下你的点赞或者...

Python_第一天(安装、基本操作、数据类型)

哈哈哈哈,开通后,还是只是简单地记录了两篇SQL学习日记。果然是我任乐的风格。 最近重新捡起了一些统计分析方法,网盘资料不全,学习了一周,还得拿起大学记录的笔记,在那里看,算是捡起了一些,学多学少,算是让自己安心一丢丢,让无处安放的心找到地方。 python总是这学习一点那儿学习一点,久久捡起来用一下,没有系统地好好学习。今天就奋起,再从零捡起来一下。能坚持几天呢,哈哈哈哈,任乐任乐。 一、安装A...

猜你喜欢

java实现自动化测试接口访问(一)

一、前置准备: PostMan 访问的网站:Github 访问的接口: https://api.github.com/search/commits?q=committer-date:2017-11-27..2017-12-01&page=1&per_page=100 实现访问:查找2017-11-27到 2017-12-01的100条数据 二、代码实现 1. 使用PostMan输入...

SQLite 真的很容易编译 | Linux 中国

事实证明,这个过程超麻烦(如通常一样),但是非常有趣! -- Julia Evans 上周,我一直在做一个 SQL 网站(https://sql-steps.wizardzines.com/,一个 SQL 示例列表)。我使用 sqlite 运行网站上的所有查询,并且我想在其中一个例子(这个)中使用窗口函数。 但是我使用的是 Ubuntu 18.04 中的 sqlite 版本,它太旧了,不支持窗口函...

关于VS2015安装Team Explorer for Microsoft Visual Studio 2015问题总结(已解决)

最近不知道怎么,想使用VS2015查看代码,但是打开VS2015的时候却提醒VS2015软件不完整?我记得自己没有动过VS2015呀!按照以往的经验,自己试了以下方法: 一、在控制面板的卸载程序中,点击VS2015的“修复”选项,但是安装到一半就会出现以下问题: 我又查看了软件Log,最后关于Team Explorer出现以下日志: 二、难道真的是安装包有问题? 把VS20...

和v-model一起来理解计算属性的响应式依赖(缓存)的概念

首先,计算属性是一个属性,当却是函数的写法,其实也不难理解,因为是要对数据进行一番操作,避免了都写在模板中,太多的逻辑会让模板过重且难以维护。 其次,计算属性不仅便于维护代码,最大的优点是响应式依赖,意思式依赖的数据只要不发生变化,不管被调用多少次,每次都立即返回之前的结果,只有依赖的数据发生改变,才会重新返回新的结果,先上一段代码说话: 这段代码中,revers是定义在methods的方法,re...

一个页面有多个echarts图形时自适应窗口大小

如上图所示一个页面有四个echarts图形:如果还写为 则只有一个图形可自适应窗口大小,另外一个则不能随窗口大小而改变图形大小, 解决办法: 为在每一个echarts图形页面将上面代码改为如下代码:  ...