一、背景
最近要开一门新课,数据库综合实习,需要实现一个图形化界面程序对SqlServer数据库进行操作,在安装好Sqlserver之后选择使用pyqt实现图形化界面。
初步设计在主界面中分为左边菜单栏和右边显示栏,需要在主窗口中嵌套一个窗口,即右边显示栏。并且需要动态改变右边的窗口。
在查相关博客时只发现两篇博客,链接地址如下:PYQT5 实现界面的嵌套、pyqt窗口嵌套。但是他们的代码太多太杂,包含了很多无关紧要的代码,而且他们的UI似乎是使用qtdesign实现的,直接导致部分代码我没看懂。。。因此我打算写下这篇博客,希望使用简介、易懂的代码介绍窗口嵌套的功能的实现。
二、思路
首选新建一个主界面mainWindow,在mainWindow中加入一个左侧布局、一个初始widget1。
在左侧布局中有两个button,通过这两个button改变右侧是显示widget1还是widget2。
三、代码
import sys
from PyQt5.Qt import *;
from PyQt5.QtWidgets import *;
if __name__ == "__main__":
app = QApplication(sys.argv)
# 主窗口
mainWin = QMainWindow()
mainWin.setGeometry(300, 300, 800, 800)
mainWin.setWindowTitle("nest windows")
# 右侧的widget 默认初始是win1 点击button切换
win1 = QWidget()
win1.setStyleSheet("background-color:red;")
win2 = QWidget()
win2.setStyleSheet("background-color:white;")
# centralWidget用来对mainWin进行布局
centralWidget = QWidget()
# 水平布局 用来放左侧菜单栏与可变的widget
hbox = QHBoxLayout()
# 垂直布局 用来放置切换widget的button
vboxLeft = QVBoxLayout()
# 两个button 用来切换右侧的 widget
btn1 = QPushButton("win1", centralWidget)
btn2 = QPushButton("win2", centralWidget)
# 将两个button放入垂直布局中
vboxLeft.addWidget(btn1)
vboxLeft.addWidget(btn2)
# hbox中加入垂直布局vboxLeft
hbox.addLayout(vboxLeft)
# hbox中加入默认的win1
hbox.addWidget(win1)
# btn1 btn2绑定点击事件
# 点击btn1 先将hbox中的第二个(下标为1)的控件的parent设置为None 再将hbox的下标1处插入一个我们希望显示的控件
btn1.clicked.connect(lambda :(hbox.itemAt(1).widget().setParent(None), hbox.insertWidget(1, win2)))
btn2.clicked.connect(lambda :(hbox.itemAt(1).widget().setParent(None), hbox.insertWidget(1, win1)))
# 将hbox布局设给centralWidget
centralWidget.setLayout(hbox)
# 将centralWidget设给mainWin
mainWin.setCentralWidget(centralWidget)
mainWin.show()
sys.exit(app.exec_())
四、最终效果
如gif图显示,点击第一个button 右侧切换为win2,点击第二个button右侧切换为win1。这里的切换是通过改变mainWin右侧的widget实现的,而不是同过改变mainWin右侧的背景色实现的。
五、注意的问题
1、之所以在新建mainWin只后还另外新建了一个centralWidget(QWidget),是因为QMainWindow类不支持设置自定义布局,需要新建一个QWidget实例,将自定义布局给QWIdget实例,再将该实例设置为QMainWindow的centralWidget。
2、在绑定button点击事件时使用了lambda函数,lambda函数一般用来实现简单的操作,比如只有一个语句的操作,如果要实现多个语句的操作,需要将多个语句放在一个括号中,语句间使用逗号分隔。
3、在更改widget时,需要先将原来的widget的parent设为None,然后再将需要显示的widget放入hbox布局中。
4、hbox.itemAt()返回的是QWidgetItem类型,没有.setParent()方法,使用hbox.itemAt().widget()即可返回widget类型。