PyQT 界面布局 ,常用的布局技巧都在这里了

2,776 阅读7分钟

一. 前言

这一篇来对 PyQT6 的布局方式做一个系统的学习,做好了系统的布局 ,就做好了创建应用的第一步。

本文目的 :

  • 了解 PyQT 的布局方式
  • 提供 PyQT 的常见布局代码
  • 本文基于 PyQT6 进行编写,可能会有版本差异

二. PyQT 组件详情

2.1 窗口组件

PyQT 中有三个类可以用于创建窗口组件 :

  • QMainWindow :可以包含菜单栏、工具栏、状态栏、标题栏等,是最常见的窗口形式,也可以说是GUI程序的主窗口
  • QDialog : 对话框窗口的基类 , 用于生成交互的对话框
  • QWidget : 基本窗口部件类 , 也是QMainWindow的基类

对窗口进行定位 :

核心的流程就在于先确定屏幕中心点 ,再移动窗口 :

from PyQt6.QtWidgets import QApplication, QMainWindow, QLabel

# 获取当前屏幕
screen = QApplication.primaryScreen()
screen_geometry = screen.availableGeometry()

# 获取屏幕中心点
screen_center = screen_geometry.center()

# 获取窗口矩形 (大小和位置)
qr = self.frameGeometry()

# 将窗口矩形的中心点移动到屏幕中心点
# qr.moveCenter(QPoint(300, 200))  -- 基于定位坐标进行屏幕的控制
qr.moveCenter(screen_center)

# 将窗口的左上角移动到计算后的矩形位置,从而实现居中
self.move(qr.topLeft())

代码很简单 ,ChatGPT 随时可以生成,重在理解其中的原理。 这段代码最核心的实际上是理解 PyQT 的坐标体系 :

image.png

  • PyQT 中通常用到的有两套坐标系 ,分别是屏幕坐标系和窗口的坐标系
  • 坐标系以左上角为原点
  • 屏幕中存在一个点为中心点 ,可以通过中心点定位窗口的整体位置
  • 常用方法 : 移动(Move), 查看当前位置 (geometry) ,设置当前位置(setGeometry),设置大小(resize

2.2 窗口内部布局组件

这里找 GPT 要了一个表格 ,先来大致看一下关于布局用的到的一些组件 :

组件名描述常用方法
QWidget所有UI组件的基类,是最基本的窗口组件。show(), hide(), resize(width, height), move(x, y), close()
QMainWindow提供标准的应用程序主窗口框架,可以包含菜单栏、工具栏和状态栏。setCentralWidget(widget), addToolBar(toolbar), statusBar(), menuBar()
QDialog对话框窗口,用于模态或非模态的用户交互。exec(), accept(), reject()
QLabel显示文本或图像的标签组件。setText(text), setPixmap(pixmap), setAlignment(alignment)
QPushButton用于触发动作的按钮组件。setText(text), clicked.connect(function), setIcon(icon)
QLineEdit单行文本输入框,用于接收用户输入。setText(text), text(), setPlaceholderText(text)
QTextEdit多行文本编辑器,可以显示和编辑富文本。setText(text), toPlainText(), setReadOnly(bool)
QCheckBox复选框,用于选择或取消选择某个选项。setChecked(bool), isChecked(), stateChanged.connect(function)
QRadioButton单选按钮,通常与其他单选按钮一起使用,以形成一个选项组。setChecked(bool), isChecked(), toggled.connect(function)
QComboBox下拉列表框,用于选择列表中的一个选项。addItem(text), currentText(), setCurrentIndex(index)
QListWidget显示和管理项目列表的组件。addItem(item), currentItem(), takeItem(row)
QTableWidget显示和管理表格数据的组件。setRowCount(count), setColumnCount(count), setItem(row, column, QTableWidgetItem)
QSlider滑动条,用于选择数值范围内的某个值。setValue(value), value(), valueChanged.connect(function)
QProgressBar进度条,用于显示操作的进度。setValue(value), setMinimum(value), setMaximum(value)
QSpinBox数值调节框,用于选择整数值。setValue(value), value(), setRange(min, max)
QDateEdit日期编辑器,用于选择日期。setDate(date), date(), setCalendarPopup(bool)
QCalendarWidget日历控件,用于显示和选择日期。setSelectedDate(date), selectedDate(), clicked.connect(function)
QFileDialog文件对话框,用于打开或保存文件。getOpenFileName(), getSaveFileName(), getExistingDirectory()
QColorDialog颜色选择对话框,用于选择颜色。getColor(), currentColor()
QFontDialog字体选择对话框,用于选择字体。getFont(), selectedFont()
QMessageBox消息框,用于显示信息、警告或错误消息。information(parent, title, text), warning(parent, title, text), critical(parent, title, text)
QToolBar工具栏,用于放置常用工具按钮。addAction(action), addWidget(widget), setMovable(bool)
QStatusBar状态栏,用于显示状态信息。showMessage(text), clearMessage(), addWidget(widget)
QVBoxLayout布局管理器,用于垂直排列控件。addWidget(widget), addLayout(layout), setSpacing(value)
QHBoxLayout布局管理器,用于水平排列控件。addWidget(widget), addLayout(layout), setSpacing(value)

核心技巧解析 :

东西很多 ,用的时候查一下资料就能掌握 ,这一篇主要关注 Layout 布局 ,有两种大类 :

  • 平行结构 : 平面各组件的布局
    • QVBoxLayout垂直布局管理器,将子组件垂直排列,一个接一个地从上到下
    • QHBoxLayout水平布局管理器,将子组件水平排列,从左到右
  • 网格结构 : 内外组件的布局 (堆叠 ,表单 ,网格 ,盒布局)
    • QGridLayout网格布局管理器,将子组件放置在一个网格中,可以通过指定行和列来定位子组件
    • QFormLayout表单布局管理器,通常用于表单布局,左侧放置标签,右侧放置输入框等组件
    • QStackedLayout堆叠布局管理器,将多个子组件叠放在同一个位置,显示其中一个子组件
    • QBoxLayout通用的盒布局管理器,可以垂直或水平排列子组件
  • 其他
    • QGroupBox : 分组框,可以将多个子组件放在一个逻辑分组中,通常带有一个标题
    • QStackedWidget : 作为一个独立的控件,允许在多个子组件之间切换
    • QSplitter : 拖动分割器布局,可以在多个子组件之间创建可拖动的分隔线

布局技巧 :

以最简单的 QVBoxLayout 和 QHBoxLayout 为例 ,设置好了父子关系就设置好了布局结构 :

image.png

比如上面这个结构 ,通过最多三层父子结构就能实现 ,最外层水平结构(level-1), 第二层垂直结构 (Level-2) , 以及最内层的 level-3 :

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QPushButton, QVBoxLayout, QHBoxLayout, QLabel


class ComplexLayoutWindow(QWidget):
    def __init__(self):
        super().__init__()

        # 创建主水平布局,用于分成左右两部分
        main_layout = QHBoxLayout()

        # ------------------ 左侧部分 ------------------
        # 创建左侧的垂直布局
        left_layout_level1 = QVBoxLayout()
        left_layout_level1.addWidget(QLabel("左侧布局"))

        # 左侧子布局 ,还是采用垂直
        left_layout_level2 = QVBoxLayout()
        left_layout_level2.addWidget(QPushButton("计算机"))
        left_layout_level2.addWidget(QPushButton("历史"))
        left_layout_level2.addWidget(QPushButton("人文"))
        left_layout_level2.addWidget(QPushButton("小说"))
        left_layout_level1.addLayout(left_layout_level2)

        # 左侧子布局 ,左下角的 button
        left_layout_level1.addWidget(QPushButton("退出"))
        left_layout_level1.addWidget(QPushButton("赞助"))

        # ------------------ 右侧部分 ------------------
        # 创建右侧的垂直布局
        right_layout_level1 = QVBoxLayout()
        right_layout_level1.addWidget(QLabel("右侧布局"))

        # 右侧水平布局一
        right_layout_level2_1 = QHBoxLayout()
        right_layout_level2_1.addWidget(QPushButton("收藏"))
        right_layout_level2_1.addWidget(QPushButton("点赞"))
        right_layout_level2_1.addWidget(QPushButton("待看"))
        right_layout_level1.addLayout(right_layout_level2_1)

        # 在右侧垂直布局二
        right_layout_level2_2 = QVBoxLayout()
        right_layout_level2_2.addWidget(QLabel("书本列表"))
        right_layout_level2_2.addWidget(QLabel("书籍一 :PyQT 界面布局 ,常用的布局技巧都在这里了"))
        right_layout_level2_2.addWidget(QLabel("书籍一 :Python 的 OpenCV 常见操作指南"))
        right_layout_level1.addLayout(right_layout_level2_2)

        # 在右侧水平布局三
        right_layout_level2_3 = QHBoxLayout()
        right_layout_level2_3.addWidget(QPushButton("上一页"))
        right_layout_level2_3.addWidget(QPushButton("下一页"))
        right_layout_level1.addLayout(right_layout_level2_3)


        # 将左侧和右侧布局添加到主水平布局中
        main_layout.addLayout(left_layout_level1)
        main_layout.addLayout(right_layout_level1)

        # 设置窗口的主布局
        self.setLayout(main_layout)

        # 设置窗口大小和标题
        self.setWindowTitle('Complex Layout Example')
        self.resize(600, 400)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = ComplexLayoutWindow()
    window.show()
    sys.exit(app.exec())

最后的结果 :

image.png

初级版本 ,丑是丑了点 ,但是基础的功能都确定好了 ,下面开始优化就行了!!!

2.3 对布局组件进行调试

这里不涉及到 QSS 的使用 ,仅以最基本的代码进行设置 :

直接基于 Size 进行大小的设置

labelA = QLabel("左侧布局")
labelA.setFixedSize(QSize(50, 10))
left_layout_level1.addWidget(labelA)

把对象包含到 QWidget 中 ,再进行大小的设定

left_container = QWidget()
left_layout_level2 = QVBoxLayout()
left_layout_level2.addWidget(QPushButton("计算机"))
left_layout_level2.addWidget(QPushButton("历史"))
left_layout_level2.addWidget(QPushButton("人文"))
left_layout_level2.addWidget(QPushButton("小说"))
left_container.setLayout(left_layout_level2)
left_container.setFixedSize(300, 400)
left_layout_level1.addWidget(left_container)

进行基础调整后 ,大致的规格就出来了。 但是最常用的方法还是使用 QSS ,这一个下一篇再详说。

三. 更加复杂的布局方式案例

上面看到了还有一些其他的布局 ,这里也简单的来看一下 :

3.1 GridLayoutWindow 网格布局

image.png

3.2 FormLayoutWindow 表单

image.png

3.3 QStackedLayout 子控件叠加

image.png

3.4 QGroupBox 分组

  • 主要功能在于将多个相关的控件分组并放入一个带标题的边框中

image.png

3.5 QSplitter 滑动框

image.png

总结

东西都是自己学习过程中的一些笔记 ,难度不大 ,但是个人感觉总结的还是比较到位了。

layout 是整个 APP 构建的第一步 ,这一步过了后面就是不断的填充细节了。

有兴趣可以长期关注 ,Python 系列会一直更新下去。

代码已更新gitee.com/antblack/Py…

最后的最后 ❤️❤️❤️👇👇👇