《老鸟python 系列》视频上线了,全网稀缺资源,涵盖python人工智能教程,爬虫教程,web教程,数据分析教程以及界面库和服务器教程,以及各个方向的主流实用项目,手把手带你从零开始进阶高手之路!点击 链接 查看详情




布局管理

阅读:231566782    分享到

目前为止,我们在界面上创建的控件,都是通过 move 函数来调整控件位置的,或者通过 setGeometry 函数来调整控件的位置和大小,这种布局我们叫做绝对定位布局。这种布局的缺陷很多,如果一个界面上控件太多,或者我们想动态调整控件的大小,显然使用上面的方式会增加编程的难度。

PyQt5 提供了相应的布局类可以对界面上的控件进行布局管理,这种布局我们叫做布局类布局,这些布局类有框布局(Boxlayout)和网格布局(QGridLayout),本节课我们就来学习这两种布局类。

框布局 Boxlayout

Boxlayout 有两种布局类,QHBoxLayout 可以创建水平布局,QVBoxLayout 可以创建垂直布局。下面我们先使用 QHBoxLayout 类对控件进行布局管理。

import sys
from PyQt5.QtWidgets import (QWidget, QPushButton, QHBoxLayout, QApplication)

class HBoxLayoutExample(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        okButton = QPushButton("OK")          # 创建一个 OK 按钮
        cancelButton = QPushButton("Cancel")  # 创建一个 Cancel 按钮

        hbox = QHBoxLayout()          # 创建一个水平布局

        hbox.addStretch(1)            # 给水平布局增加一个间隔元素,值设为 1
        hbox.addWidget(okButton)      # 给水平布局增加一个 ok 按钮
        hbox.addWidget(cancelButton)  # 给水平布局增加一个 cancel 按钮

        self.setLayout(hbox)          # 给界面加入水平布局

        self.setGeometry(600, 200, 800, 500)
        self.setWindowTitle('框布局')
        self.show()

app = QApplication(sys.argv)
ex = HBoxLayoutExample()
app.exec_()

我们在创建一个水平布局后,由于添加控件默认是从左往右自动排序的(这个可以通过 setLayoutDirection(Qt.RightToLeft)方法更改成从右往左排序),首先用 addStretch(1) 函数给布局添加一个间隔元素之后,然后再调用 addWidget 函数增加两个按钮。

addStretch(1) 中的参数是比例的意思,但是这里我们在水平方向只添加了一个间隔元素,所以不管这里的值是多少,它都会占满这里的剩余空间。比如,我们再添加一个 Strech,参数哪怕设置为 0,我们可以看到运行结果依然是两个 Strech 平分剩余空间(0:0),修改上例代码如下。

hbox.addStretch(0)     # 间隔元素值设为 0
hbox.addWidget(okButton)
hbox.addStretch(0)     # 间隔元素值设为 0
hbox.addWidget(cancelButton)

但是如果前者为 1,后者为 0,那么后者是不起作用的,修改上例代码如下。

hbox.addStretch(1)       # 间隔元素值设为 1
hbox.addWidget(okButton)
hbox.addStretch(0)       # 间隔元素值设为 0
hbox.addWidget(cancelButton)

我想现在大家对 Strech 和水平布局应该有个感性的认识了,那么怎么把这个水平布局放在右下方呢?这里是新建一个垂直方向的子布局,把上面这个水平方向布局添加到垂直布局下面,代码如下。

import sys
from PyQt5.QtWidgets import (QWidget, QPushButton, QHBoxLayout, QVBoxLayout, QApplication)

class HVBoxLayoutExample(QWidget):

    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        okButton = QPushButton("OK")          # 创建一个 OK 按钮
        cancelButton = QPushButton("Cancel")  # 创建一个 Cancel 按钮

        hbox = QHBoxLayout()          # 新建一个水平布局
        hbox.addStretch(1)            # 给水平布局增加一个间隔元素,值设为 1
        hbox.addWidget(okButton)      # 给水平布局增加一个 OK 按钮
        hbox.addWidget(cancelButton)  # 给水平布局增加一个 cancel 按钮

        vbox = QVBoxLayout()          # 新建一个垂直布局
        vbox.addStretch(1)            # 给垂直布局增加一个间隔元素,值设为 1
        vbox.addLayout(hbox)          # 给垂直布局增加上面的水平布局

        self.setLayout(vbox)          # 把垂直布局加进界面内

        self.setGeometry(600, 200, 800, 500)
        self.setWindowTitle('框布局2')
        self.show()

app = QApplication(sys.argv)
ex = HVBoxLayoutExample()
app.exec_()

网格布局 QGridLayout

QGridLayout 是将窗口分割成行和列的网格来进行排列,通常可以使用函数 addWidget 将被管理的控件添加到窗口中,或者使用 addLayout 函数将布局添加到窗口中,也可以通过 addWIdget 函数对所添加的控件设置行数与列数的跨越,最后实现网格占据多个窗格。

我们先使用单一的网格单元格,也就是一个网格里面布局一个控件。

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QGridLayout, QPushButton

class GridLayoutExample(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        grid = QGridLayout()  # 创建一个网格布局
        self.setLayout(grid)  # 给界面加入网格布局

        # 创建按钮的标签列表
        names = ['Cls', 'Back', '', 'Close',
                 '7', '8', '9', '/',
                 '4', '5', '6', '*',
                 '1', '2', '3', '-',
                 '0', '.', '=', '+']

        # 在网格中创建一个位置列表
        positions = [(i, j) for i in range(5) for j in range(4)]

        # 创建按钮并通过 addWIdget 方法添加到布局中
        for position, name in zip(positions, names):
            if name == '':
                continue

            button = QPushButton(name)
            grid.addWidget(button, *position)

        self.move(300, 150)
        self.setWindowTitle('网格布局')
        self.setGeometry(600, 200, 800, 500)
        self.show()

app = QApplication(sys.argv)
ex = GridLayoutExample()
sys.exit(app.exec_())

上面的例子中,每个控件都占用网格的一个单元格,但控件也可以使用 addWidget 重载方法,将行和列跨越更多数量的单元格。

import sys
from PyQt5.QtWidgets import (QWidget, QLabel, QLineEdit,   QTextEdit, QGridLayout, QApplication)

class GridLayoutExample2(QWidget):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        titleLabel = QLabel('标题')
        authorLabel = QLabel('作者')
        contentLabel = QLabel('内容')

        titleEdit = QLineEdit()
        authorEdit = QLineEdit()
        contentEdit = QTextEdit()

        grid = QGridLayout()
        grid.setSpacing(10)  # 设置组件之间的间距

        grid.addWidget(titleLabel, 1, 0)  # 布局在第 1 行第 0 列
        grid.addWidget(titleEdit, 1, 1)   # 布局在第 1 行第 1 列

        grid.addWidget(authorLabel, 2, 0) # 布局在第 2 行第 0 列
        grid.addWidget(authorEdit, 2, 1)  # 布局在第 2 行第 1 列

        grid.addWidget(contentLabel, 3, 0)       # 布局在第 3 行第 0 列
        grid.addWidget(contentEdit, 3, 1, 5, 1)  # 布局在第 3 行第 1 列,跨越 5 行 1 列

        self.setLayout(grid)

        self.setGeometry(600, 200, 800, 500)
        self.setWindowTitle('网格布局2')
        self.show()


app = QApplication(sys.argv)
ex = GridLayoutExample2()
app.exec_()

上面例子中,我们创建一个窗口,其中有三个标签,两个行编辑和一个文本编辑窗口小控件,然后使用 QGridLayout 完成布局。在添加一个小的控件到网格的时候,我们可以提供小部件的行和列的跨度,在上面例子中,reviewEdit 控件跨度 5 行。

本节重要知识点

掌握框布局。

掌握网格布局和网格的跨度布局。

作业

编程把我们本节例子中的计算器布局中的每个按钮的宽度增加一倍。


如果以上内容对您有帮助,请老板用微信扫一下赞赏码,赞赏后加微信号 birdpython 领取免费视频。


登录后评论

user_image
吴玺煜
2020年5月4日 00:16 回复

大佬,layout可以设置控件比例是layoutStretch吗


user_image
温赵轮
2020年5月1日 17:45 回复

感觉很多新人布局管理器用不好,界面搞得一团糟


user_image
飒蓝
2020年3月2日 01:02 回复

这个资料非常不错


user_image
地主家的傻儿子
2019年7月16日 05:14 回复

只是能调整拉伸比例,一旦在Design界面把控件套上layout,你就不能象未套上layout时调整单个控件大小了,你只能拉伸layout使控件变大小(因为控件无法用鼠标拉伸了),但拉伸layout会影响layout中的其它控件大小,所以有时你需打破布局调整个大慨又重复套layout,这样不如手写代码


user_image
朋克雪球兔
2019年6月28日 10:48 回复

layout是自适应布局,所以大小和位置是自动的,而不是手动调整。要调整,就到右下角属性栏里,调整stretch的拉伸比例


user_image
幻化成风
2019年2月9日 04:51 回复

仔细看了好久还是感觉用不利索,不得要领,这货估计还得现场演示一下才行。ui编辑器里面布局管理器就一小红线框,层数多了,鼠标拖放操作都巨麻烦,qt自带的example全都是手写布局管理器的。并没有ui编辑器里面使用布局管理器的例子。