本系列是基于Designer的PyQt教程,初衷是能不写代码就不写代码,涉及到代码、以及参数部分均由 Designer 生成,不了解Designer的读者可以花几秒钟时间读读《PyQt5写个锤子代码,画就完了》,在其他章节不做赘述。
目录
2.0 所谓堆叠布局
2.1 开始画画
2.2 设置堆叠布局
2.3 堆叠布局跨窗口调用
2.4 小结答疑
2.0 所谓堆叠布局
所谓堆叠布局,又或者说是切换页面,实质上是由一个主页面和n个分页面,在主页上掏空一块区域,将分页面堆放进去组成。所有的分页面按加入的先后顺序来排列,点击对应按钮,根据序号切换到对应的页面。
2.1 开始画画
step1 画个框架
新建一个widget,左边加一个 groupBox 放几个按钮作为切换按键,右边放个frame拿来装分页面,用合适的布局排列好按钮和窗口,并使用弹簧(spacer)把按钮顶到最高,根据喜好设置间距。每一个按钮设置好你的 objectName,留着调用。这里需要注意的是,除了frame,还有widget也是可以的,在这二者无区别。
step2 画一堆分页面
题材不限,自由发挥,新建了几个widget,设置好布局(不设置布局很丑,特别丑),同样的每个页面来个 objectName。
2.2 设置堆叠布局
画完之后生成好代码,设置堆叠布局,不了解的看本系列第一篇,后面的章节将不再提示。
以下代码注意要素:
- .addWidget() 中需要传入一个窗口类,所以需要先将各个页面继承QWidget
- self.sender() 获取当前信号的发送者,对照在index字典中获取对应索引
from PyQt5.QtWidgets import QApplication, QStackedLayout, QWidget
# 导入生成的 ui
from main_ui import Ui_main
from home_page import Ui_home_page
from blog_page import Ui_blog_page
from contact_page import Ui_contact_page
class FrameHomePage(QWidget, Ui_home_page):
def __init__(self):
super().__init__()
self.setupUi(self)
class FrameBlogPage(QWidget, Ui_blog_page):
def __init__(self):
super().__init__()
self.setupUi(self)
class FrameContactPage(QWidget, Ui_contact_page):
def __init__(self):
super().__init__()
self.setupUi(self)
class MainWidget(QWidget, Ui_main):
"""
主窗口
"""
def __init__(self):
super().__init__()
self.setupUi(self)
# 实例化一个堆叠布局
self.qsl = QStackedLayout(self.frame)
# 实例化分页面
self.home = FrameHomePage()
self.blog = FrameBlogPage()
self.contact = FrameContactPage()
# 加入到布局中
self.qsl.addWidget(self.home)
self.qsl.addWidget(self.blog)
self.qsl.addWidget(self.contact)
# 控制函数
self.controller()
def controller(self):
self.pushButton_home.clicked.connect(self.switch)
self.pushButton_blog.clicked.connect(self.switch)
self.pushButton_contact.clicked.connect(self.switch)
def switch(self):
sender = self.sender().objectName()
index = {
"pushButton_home": 0,
"pushButton_blog": 1,
"pushButton_contact": 2,
}
self.qsl.setCurrentIndex(index[sender])
2.3 跨窗口调用
前面说到,堆叠布局其实是把一堆子窗口堆放在指定区域,虽然一时间只能看到单一子窗口,实质上这些子窗口都已经展开等待被显示,这意味着这几个窗口间的状态在同一时间段,因此只需要在同一定义域(函数空间)内,将已经实例化的某窗口控件或是整个窗口当成参数传递给另一个窗口来进行操作即可,下面上实际案例:
准备了一个有文本页面和按钮页面的窗口,由按钮页面的按钮来对文本页面进行修改。在实例化阶段把textPage传入到btnPage,相应的 btnPage必须有一个参数来接收。
# 在实例化阶段把textPage传入到btnPage
self.textPage = TextPage()
self.btnPage = BtnPage(self.textPage)
# btnPage 接收并使用
class BtnPage(QWidget, Ui_btnsPage):
def __init__(self, page):
super().__init__()
self.setupUi(self)
self.textPage = page
self.controller()
def controller(self):
self.pushButton_something.clicked.connect(self.write)
self.pushButton_clear.clicked.connect(self.clear)
def write(self):
self.textPage.textEdit.setText("一堆文字啊")
def clear(self):
self.textPage.textEdit.setText('')
2.4 小结答疑
1 堆叠布局是怎么做的?
准备一个主窗口,一堆分页面,设置堆叠布局绑定到frame或者widget,通过堆叠布局实例的 setCurrent 来切换。
2 除了frame还能使用其他窗体来装吗?
能。比如widget,frame继承自widget,并在形状上追加了功能,但在布局中并无差别。
3 在跨窗口调用中,所谓的同一定义域(函数空间)具体指的是什么?
在当前例子中,指的是主窗口,所有的子窗口都由主窗口来维持状态,只要在同一主窗口内,所有子窗口都在同一空间和时间,自然可以互相调用。
我是庸了个白,你的点赞将是我更新的最大动力
<上一篇《PyQt5 写个锤子代码,画就完了》 下一篇>