PYQT5 实现界面的嵌套

2020年11月21日15:44:17 评论 75

新手,因为查阅各种博客太多,有点混,而且也找不到原本的网址了,所以就自己当作笔记记下,以便以后回来查看。

自己比较会的编程语言就只有python了,但是因为老师那边要求做一个桌面应用程序,对于python来说,我比较喜欢的就是用PYQT5了。这里简单引用下网上(https://www.jianshu.com/p/ef71566ff8bb)的说法:QT原本是诺基亚的产品,源码是用C++写的,python对QT的包装,跨平台,本地显示效果,根据系统决定,在win7就是win7的显示效果;pyqt与qt的函数接口一致,qt开发问的那个丰富,所以pyqt开发文档也比较丰富;控件丰富,函数/方法多,拖曳布局;方便打包成二进制文件;GPL协议,商业程序需要购买商业版授权。

推荐QT5的一个学习博客:https://blog.csdn.net/La_vie_est_belle/column/info/27446。总结的很好。


界面的嵌套(可能我说的不太对),在前端里面,是可以使用 iframe 这个标签实现的,但是在qt5里面,其实是可以通过 Splitter 去实现的。简单演示下:

首先主界面界面:

PYQT5 实现界面的嵌套

在Form处设置下水平布局,就如下图:

PYQT5 实现界面的嵌套

左右两侧分别是一个frame控件,左侧frame里含有两个按钮,右侧其实我只是用来占位的,后面解释。选中两个frame,点击 Lay out Horizontally in Splitter,将它设置为 Splitter 布局,为了能让要切换的界面在右侧的 frame 显示出来。

接下来是界面1:

PYQT5 实现界面的嵌套

界面2:

PYQT5 实现界面的嵌套

将三个 .ui文件转为 .py 文件,然后在代码中调整。

第一步:

在index.py文件下导入 first 和 second

  1. from first import Ui_First
  2. from second import Ui_Second

第二步:

在index.py文件下生成 first 和 second 两个子类:

  1. class First(QWidget, Ui_First):
  2. def __init__(self):
  3. super(First,self).__init__()
  4. # 子窗口初始化时实现子窗口布局
  5. self.setupUi(self)
  6. # 设置子窗体最小尺寸
  7. self.setMinimumWidth(30)
  8. self.setMinimumHeight(30)
  9. class Second(QWidget, Ui_Second):
  10. def __init__(self):
  11. super(Second,self).__init__()
  12. self.setupUi(self)
  13. self.setMinimumWidth(30)
  14. self.setMinimumHeight(30)

第三步:

在index.py的初始化里面生成两个界面的对象

  1. # 初始化两个对象,并把 first对象 加入到 splitter 中
  2. self.first = First()
  3. self.second = Second()
  4. self.splitter.addWidget(self.first)

这个时候运行可能会报错:

  1. Traceback (most recent call last):
  2. File "D:/python/workpace/Normal/cad/index.py", line 93, in <module>
  3. ui.setupUi(MainWindow)
  4. File "D:/python/workpace/Normal/cad/index.py", line 60, in setupUi
  5. self.splitter.addWidget(self.first)
  6. TypeError: addWidget(self, QWidget): argument 1 has unexpected type 'Ui_First'

原因是在 first.py 这个子界面中,是没有菜单栏等这些主界面才有的界面,因为直接用 qt 生成的 ui 文件转化的,所以代码还是带有菜单栏这些的,我们只要注释掉,并且把self.centralwidget换成 对象名即可。(同样 second.py 也要)

最后只要绑定按钮事件

  1. self.pushButton.clicked.connect(lambda :self.change(self.pushButton.objectName()))
  2. self.pushButton_2.clicked.connect(lambda :self.change(self.pushButton_2.objectName()))
  1. def change(self,name):
  2. if name == "pushButton":
  3. # 这句的意思是把现在 splitter 的界面设置为None,也就是去掉
  4. self.splitter.widget(1).setParent(None)
  5. # 把另一个self.first这个界面插入上一句去掉的那个界面的位置
  6. self.splitter.insertWidget(1, self.first)
  7. if name == "pushButton_2":
  8. self.splitter.widget(1).setParent(None)
  9. self.splitter.insertWidget(1, self.second)

这样运行,就大功告成啦

PYQT5 实现界面的嵌套PYQT5 实现界面的嵌套

 

index.py

  1. # -*- coding: utf-8 -*-
  2. # Form implementation generated from reading ui file 'index.ui'
  3. #
  4. # Created by: PyQt5 UI code generator 5.11.3
  5. #
  6. # WARNING! All changes made in this file will be lost!
  7. from PyQt5 import QtCore, QtGui, QtWidgets
  8. from PyQt5.QtWidgets import QWidget
  9. from first import Ui_First
  10. from second import Ui_Second
  11. class Ui_MainWindow(object):
  12. def setupUi(self, MainWindow):
  13. MainWindow.setObjectName("MainWindow")
  14. MainWindow.resize(800, 600)
  15. self.centralwidget = QtWidgets.QWidget(MainWindow)
  16. self.centralwidget.setObjectName("centralwidget")
  17. self.horizontalLayout = QtWidgets.QHBoxLayout(self.centralwidget)
  18. self.horizontalLayout.setObjectName("horizontalLayout")
  19. self.splitter = QtWidgets.QSplitter(self.centralwidget)
  20. self.splitter.setOrientation(QtCore.Qt.Horizontal)
  21. self.splitter.setObjectName("splitter")
  22. self.frame = QtWidgets.QFrame(self.splitter)
  23. self.frame.setMaximumSize(QtCore.QSize(200, 16777215))
  24. self.frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
  25. self.frame.setFrameShadow(QtWidgets.QFrame.Raised)
  26. self.frame.setObjectName("frame")
  27. self.verticalLayout = QtWidgets.QVBoxLayout(self.frame)
  28. self.verticalLayout.setObjectName("verticalLayout")
  29. self.pushButton = QtWidgets.QPushButton(self.frame)
  30. self.pushButton.setObjectName("pushButton")
  31. self.verticalLayout.addWidget(self.pushButton)
  32. self.pushButton_2 = QtWidgets.QPushButton(self.frame)
  33. self.pushButton_2.setObjectName("pushButton_2")
  34. self.verticalLayout.addWidget(self.pushButton_2)
  35. # 这里注释掉,因为不需要frame2。当初在qt 里面设计这个frame2的原因是为了占位,不至于到时候布局出现错乱。
  36. # self.frame_2 = QtWidgets.QFrame(self.splitter)
  37. # self.frame_2.setStyleSheet("background-color:white;")
  38. # self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
  39. # self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
  40. # self.frame_2.setObjectName("frame_2")
  41. self.horizontalLayout.addWidget(self.splitter)
  42. MainWindow.setCentralWidget(self.centralwidget)
  43. self.menubar = QtWidgets.QMenuBar(MainWindow)
  44. self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
  45. self.menubar.setObjectName("menubar")
  46. MainWindow.setMenuBar(self.menubar)
  47. self.statusbar = QtWidgets.QStatusBar(MainWindow)
  48. self.statusbar.setObjectName("statusbar")
  49. MainWindow.setStatusBar(self.statusbar)
  50. # 初始化两个对象,并把 first对象 加入到 splitter 中
  51. self.first = First()
  52. self.second = Second()
  53. self.splitter.addWidget(self.first)
  54. self.pushButton.clicked.connect(lambda :self.change(self.pushButton.objectName()))
  55. self.pushButton_2.clicked.connect(lambda :self.change(self.pushButton_2.objectName()))
  56. self.retranslateUi(MainWindow)
  57. QtCore.QMetaObject.connectSlotsByName(MainWindow)
  58. def retranslateUi(self, MainWindow):
  59. _translate = QtCore.QCoreApplication.translate
  60. MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
  61. self.pushButton.setText(_translate("MainWindow", "界面1"))
  62. self.pushButton_2.setText(_translate("MainWindow", "界面2"))
  63. def change(self,name):
  64. if name == "pushButton":
  65. self.splitter.widget(1).setParent(None)
  66. self.splitter.insertWidget(1, self.first)
  67. if name == "pushButton_2":
  68. self.splitter.widget(1).setParent(None)
  69. self.splitter.insertWidget(1, self.second)
  70. class First(QWidget, Ui_First):
  71. def __init__(self):
  72. super(First,self).__init__()
  73. # 子窗口初始化时实现子窗口布局
  74. self.setupUi(self)
  75. # 设置子窗体最小尺寸
  76. self.setMinimumWidth(30)
  77. self.setMinimumHeight(30)
  78. class Second(QWidget, Ui_Second):
  79. def __init__(self):
  80. super(Second,self).__init__()
  81. self.setupUi(self)
  82. self.setMinimumWidth(30)
  83. self.setMinimumHeight(30)
  84. if __name__ == '__main__':
  85. import sys
  86. app = QtWidgets.QApplication(sys.argv)
  87. MainWindow = QtWidgets.QMainWindow()
  88. ui = Ui_MainWindow()
  89. ui.setupUi(MainWindow)
  90. MainWindow.show()
  91. sys.exit(app.exec_())

first.py

  1. # -*- coding: utf-8 -*-
  2. # Form implementation generated from reading ui file 'first.ui'
  3. #
  4. # Created by: PyQt5 UI code generator 5.11.3
  5. #
  6. # WARNING! All changes made in this file will be lost!
  7. from PyQt5 import QtCore, QtGui, QtWidgets
  8. class Ui_First(object):
  9. def setupUi(self, Ui_First):
  10. Ui_First.setObjectName("MainWindow")
  11. Ui_First.resize(800, 600)
  12. # self.centralwidget = QtWidgets.QWidget(Ui_First)
  13. # self.centralwidget.setObjectName("centralwidget")
  14. self.horizontalLayout = QtWidgets.QHBoxLayout(Ui_First)
  15. self.horizontalLayout.setObjectName("horizontalLayout")
  16. self.frame_2 = QtWidgets.QFrame(Ui_First)
  17. self.frame_2.setStyleSheet("background-color:white;")
  18. self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
  19. self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
  20. self.frame_2.setObjectName("frame_2")
  21. self.label = QtWidgets.QLabel(self.frame_2)
  22. self.label.setGeometry(QtCore.QRect(300, 180, 181, 81))
  23. font = QtGui.QFont()
  24. font.setPointSize(20)
  25. font.setBold(True)
  26. font.setWeight(75)
  27. self.label.setFont(font)
  28. self.label.setObjectName("label")
  29. self.horizontalLayout.addWidget(self.frame_2)
  30. # Ui_First.setCentralWidget(self.centralwidget)
  31. # self.menubar = QtWidgets.QMenuBar(Ui_First)
  32. # self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
  33. # self.menubar.setObjectName("menubar")
  34. # Ui_First.setMenuBar(self.menubar)
  35. # self.statusbar = QtWidgets.QStatusBar(Ui_First)
  36. # self.statusbar.setObjectName("statusbar")
  37. # Ui_First.setStatusBar(self.statusbar)
  38. self.retranslateUi(Ui_First)
  39. QtCore.QMetaObject.connectSlotsByName(Ui_First)
  40. def retranslateUi(self, MainWindow):
  41. _translate = QtCore.QCoreApplication.translate
  42. MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
  43. self.label.setText(_translate("MainWindow", "这是界面1"))

second.py

  1. # -*- coding: utf-8 -*-
  2. # Form implementation generated from reading ui file 'second.ui'
  3. #
  4. # Created by: PyQt5 UI code generator 5.11.3
  5. #
  6. # WARNING! All changes made in this file will be lost!
  7. from PyQt5 import QtCore, QtGui, QtWidgets
  8. class Ui_Second(object):
  9. def setupUi(self, Ui_Second):
  10. Ui_Second.setObjectName("MainWindow")
  11. Ui_Second.resize(800, 600)
  12. # self.centralwidget = QtWidgets.QWidget(Ui_Second)
  13. # self.centralwidget.setObjectName("centralwidget")
  14. self.horizontalLayout = QtWidgets.QHBoxLayout(Ui_Second)
  15. self.horizontalLayout.setObjectName("horizontalLayout")
  16. self.frame_2 = QtWidgets.QFrame(Ui_Second)
  17. self.frame_2.setStyleSheet("background-color:green;")
  18. self.frame_2.setFrameShape(QtWidgets.QFrame.StyledPanel)
  19. self.frame_2.setFrameShadow(QtWidgets.QFrame.Raised)
  20. self.frame_2.setObjectName("frame_2")
  21. self.label = QtWidgets.QLabel(self.frame_2)
  22. self.label.setGeometry(QtCore.QRect(300, 180, 181, 81))
  23. font = QtGui.QFont()
  24. font.setPointSize(20)
  25. font.setBold(True)
  26. font.setWeight(75)
  27. self.label.setFont(font)
  28. self.label.setObjectName("label")
  29. self.horizontalLayout.addWidget(self.frame_2)
  30. # Ui_Second.setCentralWidget(self.centralwidget)
  31. # self.menubar = QtWidgets.QMenuBar(Ui_Second)
  32. # self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 23))
  33. # self.menubar.setObjectName("menubar")
  34. # Ui_Second.setMenuBar(self.menubar)
  35. # self.statusbar = QtWidgets.QStatusBar(Ui_Second)
  36. # self.statusbar.setObjectName("statusbar")
  37. # Ui_Second.setStatusBar(self.statusbar)
  38. self.retranslateUi(Ui_Second)
  39. QtCore.QMetaObject.connectSlotsByName(Ui_Second)
  40. def retranslateUi(self, MainWindow):
  41. _translate = QtCore.QCoreApplication.translate
  42. MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
  43. self.label.setText(_translate("MainWindow", "这是界面2"))
阿成哥
  • 本文由 发表于 2020年11月21日15:44:17
  • 转载请务必保留本文链接:https://blog.acwang.com/?p=46