4. 布局管理:水平布局、垂直布局、网格布局、表单布局、嵌套布局实战

布局管理,说白了就是解决「控件往哪儿放」的问题。

我刚开始做HMI的时候,觉得布局嘛,拖拖拽拽不就行了?结果项目一复杂,界面一多,维护起来简直想砸电脑。后来我才明白——好的布局,是HMI系统的骨架。骨架歪了,皮相再好看也没用。

4.1 水平布局(QHBoxLayout)

水平布局,就是把控件从左到右排成一排。最典型的场景——工具栏、状态栏、按钮组

我个人习惯,在需要「并排操作」的地方用水平布局。比如一个启动按钮、一个停止按钮、一个急停按钮,排在一起,操作顺手。

核心要点:水平布局里的控件,默认会平分空间。你可以通过设置 stretch(拉伸因子)来控制谁占得多、谁占得少。
# 水平布局示例
from PyQt5.QtWidgets import QApplication, QWidget, QHBoxLayout, QPushButton
import sys

app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle('水平布局示例')

layout = QHBoxLayout()

btn1 = QPushButton('启动')
btn2 = QPushButton('停止')
btn3 = QPushButton('急停')

# 设置拉伸因子:启动和停止各占1份,急停占2份
layout.addWidget(btn1, 1)
layout.addWidget(btn2, 1)
layout.addWidget(btn3, 2)

window.setLayout(layout)
window.show()
sys.exit(app.exec_())
我的经验:急停按钮我通常会设大一点,方便操作工在紧急情况下快速拍下。拉伸因子设成2,视觉上更突出。

4.2 垂直布局(QVBoxLayout)

垂直布局,就是从上到下排。适合参数设置面板、日志显示区、菜单列表

我在项目中遇到过一个问题——参数设置项太多,一屏显示不完。后来我用垂直布局配合滚动区域,完美解决。

# 垂直布局示例
from PyQt5.QtWidgets import QVBoxLayout, QLabel, QLineEdit

layout = QVBoxLayout()

layout.addWidget(QLabel('温度设定:'))
layout.addWidget(QLineEdit())
layout.addWidget(QLabel('压力设定:'))
layout.addWidget(QLineEdit())
layout.addWidget(QLabel('速度设定:'))
layout.addWidget(QLineEdit())

# 这样从上到下,依次排列,清晰明了
注意:垂直布局里如果控件太多,记得加 QScrollArea。否则界面会超出屏幕,操作工点不到下面的按钮——我曾经因为这个被现场投诉过。

4.3 网格布局(QGridLayout)

网格布局,就是表格形式。行和列交叉,每个格子放一个控件。这是工业HMI里最常用、最实用的布局方式。

你想想看,一个监控画面,左上角显示温度,右上角显示压力,左下角显示流量,右下角显示液位——这不就是网格布局吗?

# 网格布局示例
from PyQt5.QtWidgets import QGridLayout

grid = QGridLayout()

# 参数:控件,行,列,行跨度,列跨度
grid.addWidget(QLabel('温度'), 0, 0, 1, 1)
grid.addWidget(QLabel('压力'), 0, 1, 1, 1)
grid.addWidget(QLabel('流量'), 1, 0, 1, 1)
grid.addWidget(QLabel('液位'), 1, 1, 1, 1)

# 2行2列,每个格子放一个标签
控件 说明
0 0 温度显示 左上角
0 1 压力显示 右上角
1 0 流量显示 左下角
1 1 液位显示 右下角
关键技巧:网格布局支持跨行跨列。比如你想让一个「总览图」占两列,可以设列跨度为2。

4.4 表单布局(QFormLayout)

表单布局,专门用来做「标签+输入框」这种配对。比如参数设置界面——左边是参数名,右边是输入框。

我以前傻乎乎地用网格布局手动对齐,后来发现 Qt 有现成的 QFormLayout,两行代码搞定。

# 表单布局示例
from PyQt5.QtWidgets import QFormLayout

form = QFormLayout()

form.addRow('温度上限:', QLineEdit())
form.addRow('温度下限:', QLineEdit())
form.addRow('压力上限:', QLineEdit())
form.addRow('压力下限:', QLineEdit())

# 自动左对齐标签,右对齐输入框,省心省力
避坑指南:我曾经在表单布局里混用不同高度的控件,结果对齐乱七八糟。后来我统一用 QLineEdit,高度一致,界面才整齐。

4.5 嵌套布局实战

嵌套布局,就是把上面几种布局组合起来用。一个复杂的HMI界面,往往是「布局套布局」。

举个例子:一个典型的监控画面——

  • 最外层是垂直布局
  • 顶部是水平布局(放标题和报警灯)
  • 中间是网格布局(放各个监控参数)
  • 底部是水平布局(放操作按钮)
# 嵌套布局实战
from PyQt5.QtWidgets import *

app = QApplication([])
window = QWidget()
window.setWindowTitle('嵌套布局实战')

# 最外层:垂直布局
main_layout = QVBoxLayout()

# 顶部:水平布局
top_layout = QHBoxLayout()
top_layout.addWidget(QLabel('生产线监控系统'))
top_layout.addWidget(QPushButton('报警确认'))
top_layout.addStretch()  # 弹性空间,把按钮推到右边

# 中间:网格布局
grid_layout = QGridLayout()
grid_layout.addWidget(QLabel('温度:25°C'), 0, 0)
grid_layout.addWidget(QLabel('压力:0.5MPa'), 0, 1)
grid_layout.addWidget(QLabel('流量:120L/min'), 1, 0)
grid_layout.addWidget(QLabel('液位:75%'), 1, 1)

# 底部:水平布局
bottom_layout = QHBoxLayout()
bottom_layout.addWidget(QPushButton('启动'))
bottom_layout.addWidget(QPushButton('停止'))
bottom_layout.addWidget(QPushButton('急停'))

# 组装
main_layout.addLayout(top_layout)
main_layout.addLayout(grid_layout)
main_layout.addLayout(bottom_layout)

window.setLayout(main_layout)
window.show()
app.exec_()
嵌套布局的核心思想:先分块,再填充。就像搭积木,先搭大框架,再往里面塞小积木。

4.6 布局管理避坑指南

  • 不要硬编码坐标:用 setGeometry() 固定位置,分辨率一变就乱套。用布局管理器,自动适应。
  • 注意边距和间距:setContentsMargins() 和 setSpacing() 要调好。太挤了看着难受,太散了浪费空间。
  • 善用 stretch:拉伸因子是布局的灵魂。不会用 stretch,布局就失去了灵活性。
  • 测试不同分辨率:我曾在 1024x768 上调试好的界面,到 1920x1080 上按钮挤成一团。后来我强制设最小尺寸,才解决问题。
我曾经踩过的坑:在嵌套布局里忘了 addStretch(),结果控件全部挤在左边。现场操作工说「你这界面怎么半边是空的?」——尴尬。

好了,布局管理就讲到这里。记住一句话:布局是骨架,控件是血肉。骨架搭好了,后面加功能、改界面,都轻松。

下一章,我们聊聊信号与槽——HMI的「神经中枢」。到时候见。