窗口变大时,布局要决定多出来的空间交给谁;窗口变小时,又要决定哪些控件可以收缩。QSizePolicy 表达控件意愿,sizeHint() 提供建议尺寸,最小和最大尺寸给出约束,布局的 stretch 则表达同方向项目之间的相对伸缩权重。
1. 先分清四个量
跳转到“1. 先分清四个量”| 设置 | 回答的问题 | 常见误解 |
|---|---|---|
sizeHint() | 控件认为多大合适? | 它不保证最终尺寸 |
minimumSize、maximumSize | 尺寸不能越过什么边界? | Expanding 不会解除固定宽高 |
QSizePolicy | 能否伸缩、是否希望利用额外空间? | 它不是一个像素尺寸 |
| 布局 stretch | 同一布局的主方向上,谁获得更大的份额? | 权重不是百分比,也不是子控件编号 |
Qt 的布局管理说明与 QWidget 尺寸文档共同规定这些信息如何参与布局。对于有最小宽度、最大宽度或不同尺寸提示的控件,最终比例还会受边界约束。
2. Expanding 实际表示什么
跳转到“2. Expanding 实际表示什么”原笔记中的代码:
overallContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);第一个参数用于水平方向,第二个用于垂直方向。这表示控件能够伸缩,而且能有效利用额外空间,适合图表、文本编辑区等内容区域。它并不命令控件忽略兄弟控件或填满整个窗口。
常见策略可以这样选择:
| 策略 | 相对尺寸提示的行为 | 典型意图 |
|---|---|---|
Fixed | 不伸不缩 | 尺寸应保持稳定 |
Minimum | 可以长大,不希望小于提示尺寸 | 完整显示内容 |
Maximum | 可以缩小,不需要超过提示尺寸 | 限制不必要扩张 |
Preferred | 可以伸缩,提示尺寸最合适 | 普通控件的默认偏好 |
Expanding | 可以伸缩,希望多分空间 | 主要内容区域 |
MinimumExpanding | 提示尺寸是下限,希望长大 | 保持最低可用空间 |
Ignored | 忽略尺寸提示参与分配 | 仅在明确掌握尺寸约束时使用 |
这些含义来自 QSizePolicy 的策略定义。实际设计还需检查文本换行、最小尺寸和布局内边距。
3. setStretch(4, 1) 的两个参数
跳转到“3. setStretch(4, 1) 的两个参数”workspaceLayout->setStretch(4, 1);对于 QHBoxLayout 或 QVBoxLayout:
4是布局项目的零起始索引,指第 5 个项目。1是相对伸缩权重。- 横向布局分配宽度,纵向布局分配高度。
- 布局项目可以是控件、子布局或间隔;插入新项目后,数字索引可能改变。
若没有其他正权重,权重为 1 的可扩展项目通常会承担主要剩余空间;其他项目仍须满足自身尺寸约束。若两个无额外限制的区域权重分别为 1 和 3,可用空间充足时会趋近 1:3。不要把任何布局的最终像素宽度都承诺为严格 1:3。
已知控件时可以减少索引误用:
const bool found = workspaceLayout->setStretchFactor(overallContainer, 1);Q_ASSERT(found);这只寻找该布局直接包含的项目,不递归查找所有子布局。依据:QBoxLayout 的 stretch 接口。
4. 可运行的两栏布局
跳转到“4. 可运行的两栏布局”下面示例适用于 Qt 6 Widgets。左侧导航和右侧编辑区都允许扩展,布局权重分别为 1 与 3。
#include <QApplication>#include <QHBoxLayout>#include <QListWidget>#include <QSizePolicy>#include <QTextEdit>#include <QWidget>
int main(int argc, char *argv[]) { QApplication app(argc, argv); QWidget window; auto *layout = new QHBoxLayout(&window); auto *navigation = new QListWidget; auto *editor = new QTextEdit;
navigation->addItems({"Overview", "Measurements", "Notes"}); editor->setPlainText("Resize the window to inspect the layout."); navigation->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); editor->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); layout->addWidget(navigation, 1); layout->addWidget(editor, 3);
window.resize(960, 540); window.show(); return app.exec();}保存为 main.cpp,最小 CMakeLists.txt 为:
cmake_minimum_required(VERSION 3.21)project(LayoutDemo LANGUAGES CXX)set(CMAKE_CXX_STANDARD 17)find_package(Qt6 REQUIRED COMPONENTS Widgets)add_executable(layout-demo main.cpp)target_link_libraries(layout-demo PRIVATE Qt6::Widgets)构建时让 CMAKE_PREFIX_PATH 指向本机 Qt 开发套件。先拖大、再缩小窗口;到达控件的最小尺寸时观察比例变化,比只在一种窗口尺寸下截图更能检验布局。
5. “设了 Expanding 仍不生效”的检查顺序
跳转到“5. “设了 Expanding 仍不生效”的检查顺序”- 确认控件加入了目标布局,布局也已安装到显示中的父控件。
- 查找
setFixedWidth、setFixedHeight、最大尺寸和样式表尺寸限制。 - 确认改的是横向还是纵向;检查直接父布局和上层布局各自的约束。
- 确认
setStretch的索引未因插入间隔或嵌套布局而偏移。 - 检查
addWidget的 alignment;指定居中等对齐可能让控件不填满分配给它的单元。
本页把原先两个仅有 TODO 和相同代码行的记录整合为同一问题链:先理解控件尺寸意愿,再理解布局空间分配。