一. 前言
这一篇来对 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 的坐标体系 :
- 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 为例 ,设置好了父子关系就设置好了布局结构 :
比如上面这个结构 ,通过最多三层父子结构就能实现 ,最外层水平结构(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())
最后的结果 :
初级版本 ,丑是丑了点 ,但是基础的功能都确定好了 ,下面开始优化就行了!!!
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 网格布局
3.2 FormLayoutWindow 表单
3.3 QStackedLayout 子控件叠加
3.4 QGroupBox 分组
- 主要功能在于将多个相关的控件分组并放入一个带标题的边框中
3.5 QSplitter 滑动框
总结
东西都是自己学习过程中的一些笔记 ,难度不大 ,但是个人感觉总结的还是比较到位了。
layout 是整个 APP 构建的第一步 ,这一步过了后面就是不断的填充细节了。
有兴趣可以长期关注 ,Python 系列会一直更新下去。
代码已更新 : gitee.com/antblack/Py…
最后的最后 ❤️❤️❤️👇👇👇
- 👈 欢迎关注 ,超200篇优质文章,未来持续高质量输出 🎉🎉
- 🔥🔥🔥 系列文章集合,高并发,源码应有尽有 👍👍
- 走过路过不要错过 ,知识无价还不收钱 ❗❗