欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

PYQT5 实现界面的嵌套方式

程序员文章站 2022-07-06 17:12:40
新手,因为查阅各种博客太多,有点混,而且也找不到原本的网址了,所以就自己当作笔记记下,以便以后回来查看。自己比较会的编程语言就只有python了,但是因为老师那边要求做一个桌面应用程序,对于pytho...

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

自己比较会的编程语言就只有python了,但是因为老师那边要求做一个桌面应用程序,对于python来说,我比较喜欢的就是用pyqt5了。

这里简单引用下网上的说法:qt原本是诺基亚的产品,源码是用c++写的,python对qt的包装,跨平台,本地显示效果,根据系统决定,在win7就是win7的显示效果;pyqt与qt的函数接口一致,qt开发问的那个丰富,所以pyqt开发文档也比较丰富;控件丰富,函数/方法多,拖曳布局;方便打包成二进制文件;gpl协议,商业程序需要购买商业版授权。

界面的嵌套(可能我说的不太对),在前端里面,是可以使用 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

from first import ui_first
from second import ui_second

第二步:

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

class first(qwidget, ui_first):
  def __init__(self):
    super(first,self).__init__()
    # 子窗口初始化时实现子窗口布局
    self.setupui(self)
    # 设置子窗体最小尺寸
    self.setminimumwidth(30)
    self.setminimumheight(30)
 
class second(qwidget, ui_second):
  def __init__(self):
    super(second,self).__init__()
    self.setupui(self)
    self.setminimumwidth(30)
    self.setminimumheight(30)

第三步:

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

# 初始化两个对象,并把 first对象 加入到 splitter 中
self.first = first()
self.second = second()
self.splitter.addwidget(self.first)

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

traceback (most recent call last):
file "d:/python/workpace/normal/cad/index.py", line 93, in <module>
ui.setupui(mainwindow)
file "d:/python/workpace/normal/cad/index.py", line 60, in setupui
self.splitter.addwidget(self.first)
typeerror: addwidget(self, qwidget): argument 1 has unexpected type 'ui_first'

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

最后只要绑定按钮事件

self.pushbutton.clicked.connect(lambda :self.change(self.pushbutton.objectname()))
self.pushbutton_2.clicked.connect(lambda :self.change(self.pushbutton_2.objectname()))
  def change(self,name):
    if name == "pushbutton":
      # 这句的意思是把现在 splitter 的界面设置为none,也就是去掉
      self.splitter.widget(1).setparent(none)
      # 把另一个self.first这个界面插入上一句去掉的那个界面的位置
      self.splitter.insertwidget(1, self.first)
 
    if name == "pushbutton_2":
      self.splitter.widget(1).setparent(none)
      self.splitter.insertwidget(1, self.second)

这样运行,就大功告成啦

PYQT5 实现界面的嵌套方式

index.py

# -*- coding: utf-8 -*- 
# form implementation generated from reading ui file 'index.ui'
#
# created by: pyqt5 ui code generator 5.11.3
#
# warning! all changes made in this file will be lost!
 
from pyqt5 import qtcore, qtgui, qtwidgets
from pyqt5.qtwidgets import qwidget
from first import ui_first
from second import ui_second
 
class ui_mainwindow(object):
  def setupui(self, mainwindow):
    mainwindow.setobjectname("mainwindow")
    mainwindow.resize(800, 600)
    self.centralwidget = qtwidgets.qwidget(mainwindow)
    self.centralwidget.setobjectname("centralwidget")
    self.horizontallayout = qtwidgets.qhboxlayout(self.centralwidget)
    self.horizontallayout.setobjectname("horizontallayout")
    self.splitter = qtwidgets.qsplitter(self.centralwidget)
    self.splitter.setorientation(qtcore.qt.horizontal)
    self.splitter.setobjectname("splitter")
    self.frame = qtwidgets.qframe(self.splitter)
    self.frame.setmaximumsize(qtcore.qsize(200, 16777215))
    self.frame.setframeshape(qtwidgets.qframe.styledpanel)
    self.frame.setframeshadow(qtwidgets.qframe.raised)
    self.frame.setobjectname("frame")
    self.verticallayout = qtwidgets.qvboxlayout(self.frame)
    self.verticallayout.setobjectname("verticallayout")
    self.pushbutton = qtwidgets.qpushbutton(self.frame)
    self.pushbutton.setobjectname("pushbutton")
    self.verticallayout.addwidget(self.pushbutton)
    self.pushbutton_2 = qtwidgets.qpushbutton(self.frame)
    self.pushbutton_2.setobjectname("pushbutton_2")
    self.verticallayout.addwidget(self.pushbutton_2)
 
    # 这里注释掉,因为不需要frame2。当初在qt 里面设计这个frame2的原因是为了占位,不至于到时候布局出现错乱。
    # self.frame_2 = qtwidgets.qframe(self.splitter)
    # self.frame_2.setstylesheet("background-color:white;")
    # self.frame_2.setframeshape(qtwidgets.qframe.styledpanel)
    # self.frame_2.setframeshadow(qtwidgets.qframe.raised)
    # self.frame_2.setobjectname("frame_2")
 
    self.horizontallayout.addwidget(self.splitter)
    mainwindow.setcentralwidget(self.centralwidget)
    self.menubar = qtwidgets.qmenubar(mainwindow)
    self.menubar.setgeometry(qtcore.qrect(0, 0, 800, 23))
    self.menubar.setobjectname("menubar")
    mainwindow.setmenubar(self.menubar)
    self.statusbar = qtwidgets.qstatusbar(mainwindow)
    self.statusbar.setobjectname("statusbar")
    mainwindow.setstatusbar(self.statusbar)
 
    # 初始化两个对象,并把 first对象 加入到 splitter 中
    self.first = first()
    self.second = second()
    self.splitter.addwidget(self.first)
 
    self.pushbutton.clicked.connect(lambda :self.change(self.pushbutton.objectname()))
    self.pushbutton_2.clicked.connect(lambda :self.change(self.pushbutton_2.objectname()))
 
    self.retranslateui(mainwindow)
    qtcore.qmetaobject.connectslotsbyname(mainwindow)
 
  def retranslateui(self, mainwindow):
    _translate = qtcore.qcoreapplication.translate
    mainwindow.setwindowtitle(_translate("mainwindow", "mainwindow"))
    self.pushbutton.settext(_translate("mainwindow", "界面1"))
    self.pushbutton_2.settext(_translate("mainwindow", "界面2"))
 
  def change(self,name):
    if name == "pushbutton":
      self.splitter.widget(1).setparent(none)
      self.splitter.insertwidget(1, self.first)
 
    if name == "pushbutton_2":
      self.splitter.widget(1).setparent(none)
      self.splitter.insertwidget(1, self.second)
 
class first(qwidget, ui_first):
  def __init__(self):
    super(first,self).__init__()
    # 子窗口初始化时实现子窗口布局
    self.setupui(self)
 
    # 设置子窗体最小尺寸
    self.setminimumwidth(30)
    self.setminimumheight(30)
 
class second(qwidget, ui_second):
  def __init__(self):
    super(second,self).__init__()
    self.setupui(self)
    self.setminimumwidth(30)
    self.setminimumheight(30)
 
if __name__ == '__main__':
  import sys
  app = qtwidgets.qapplication(sys.argv)
  mainwindow = qtwidgets.qmainwindow()
  ui = ui_mainwindow()
  ui.setupui(mainwindow)
  mainwindow.show()
  sys.exit(app.exec_())

first.py

# -*- coding: utf-8 -*-
 
# form implementation generated from reading ui file 'first.ui'
#
# created by: pyqt5 ui code generator 5.11.3
#
# warning! all changes made in this file will be lost!
 
from pyqt5 import qtcore, qtgui, qtwidgets 
class ui_first(object):
  def setupui(self, ui_first):
    ui_first.setobjectname("mainwindow")
    ui_first.resize(800, 600)
    # self.centralwidget = qtwidgets.qwidget(ui_first)
    # self.centralwidget.setobjectname("centralwidget")
    self.horizontallayout = qtwidgets.qhboxlayout(ui_first)
    self.horizontallayout.setobjectname("horizontallayout")
    self.frame_2 = qtwidgets.qframe(ui_first)
    self.frame_2.setstylesheet("background-color:white;")
    self.frame_2.setframeshape(qtwidgets.qframe.styledpanel)
    self.frame_2.setframeshadow(qtwidgets.qframe.raised)
    self.frame_2.setobjectname("frame_2")
    self.label = qtwidgets.qlabel(self.frame_2)
    self.label.setgeometry(qtcore.qrect(300, 180, 181, 81))
    font = qtgui.qfont()
    font.setpointsize(20)
    font.setbold(true)
    font.setweight(75)
    self.label.setfont(font)
    self.label.setobjectname("label")
    self.horizontallayout.addwidget(self.frame_2)
    # ui_first.setcentralwidget(self.centralwidget)
    # self.menubar = qtwidgets.qmenubar(ui_first)
    # self.menubar.setgeometry(qtcore.qrect(0, 0, 800, 23))
    # self.menubar.setobjectname("menubar")
    # ui_first.setmenubar(self.menubar)
    # self.statusbar = qtwidgets.qstatusbar(ui_first)
    # self.statusbar.setobjectname("statusbar")
    # ui_first.setstatusbar(self.statusbar)
 
    self.retranslateui(ui_first)
    qtcore.qmetaobject.connectslotsbyname(ui_first)
 
  def retranslateui(self, mainwindow):
    _translate = qtcore.qcoreapplication.translate
    mainwindow.setwindowtitle(_translate("mainwindow", "mainwindow"))
    self.label.settext(_translate("mainwindow", "这是界面1"))
 

second.py

# -*- coding: utf-8 -*-
 
# form implementation generated from reading ui file 'second.ui'
#
# created by: pyqt5 ui code generator 5.11.3
#
# warning! all changes made in this file will be lost!
 
from pyqt5 import qtcore, qtgui, qtwidgets 
class ui_second(object):
  def setupui(self, ui_second):
    ui_second.setobjectname("mainwindow")
    ui_second.resize(800, 600)
    # self.centralwidget = qtwidgets.qwidget(ui_second)
    # self.centralwidget.setobjectname("centralwidget")
    self.horizontallayout = qtwidgets.qhboxlayout(ui_second)
    self.horizontallayout.setobjectname("horizontallayout")
    self.frame_2 = qtwidgets.qframe(ui_second)
    self.frame_2.setstylesheet("background-color:green;")
    self.frame_2.setframeshape(qtwidgets.qframe.styledpanel)
    self.frame_2.setframeshadow(qtwidgets.qframe.raised)
    self.frame_2.setobjectname("frame_2")
    self.label = qtwidgets.qlabel(self.frame_2)
    self.label.setgeometry(qtcore.qrect(300, 180, 181, 81))
    font = qtgui.qfont()
    font.setpointsize(20)
    font.setbold(true)
    font.setweight(75)
    self.label.setfont(font)
    self.label.setobjectname("label")
    self.horizontallayout.addwidget(self.frame_2)
    # ui_second.setcentralwidget(self.centralwidget)
    # self.menubar = qtwidgets.qmenubar(ui_second)
    # self.menubar.setgeometry(qtcore.qrect(0, 0, 800, 23))
    # self.menubar.setobjectname("menubar")
    # ui_second.setmenubar(self.menubar)
    # self.statusbar = qtwidgets.qstatusbar(ui_second)
    # self.statusbar.setobjectname("statusbar")
    # ui_second.setstatusbar(self.statusbar)
 
    self.retranslateui(ui_second)
    qtcore.qmetaobject.connectslotsbyname(ui_second) 
  def retranslateui(self, mainwindow):
    _translate = qtcore.qcoreapplication.translate
    mainwindow.setwindowtitle(_translate("mainwindow", "mainwindow"))
    self.label.settext(_translate("mainwindow", "这是界面2"))
 

以上为个人经验,希望能给大家一个参考,也希望大家多多支持。如有错误或未考虑完全的地方,望不吝赐教。