Qt 布局管理 #
布局概述 #
Qt 的布局管理系统自动调整控件的大小和位置,确保界面在不同窗口大小下都能正确显示。
text
┌─────────────────────────────────────────────────────────────┐
│ Qt 布局类型 │
├─────────────────────────────────────────────────────────────┤
│ │
│ QBoxLayout │
│ ├── QHBoxLayout - 水平布局 │
│ └── QVBoxLayout - 垂直布局 │
│ │
│ QGridLayout - 网格布局 │
│ │
│ QFormLayout - 表单布局 │
│ │
│ QStackedLayout - 堆栈布局 │
│ │
│ QFlowLayout - 流式布局(Qt 6.5+) │
│ │
└─────────────────────────────────────────────────────────────┘
布局基础 #
为什么需要布局? #
text
┌─────────────────────────────────────────────────────────────┐
│ 固定位置 vs 布局 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 固定位置问题: │
│ ┌─────────────────────────────────┐ │
│ │ [Button1] (100, 50) │ │
│ │ [Button2] (200, 50) │ │
│ │ │ │
│ │ 窗口放大后: │ │
│ │ [Button1] [Button2] │ │
│ │ │ │
│ │ │ 空白区域 │
│ │ │ │
│ │ │ │
│ └─────────────────────────────────┘ │
│ │
│ 使用布局: │
│ ┌─────────────────────────────────┐ │
│ │ [ Button1 ] [ Button2 ] │ 自动适应窗口大小 │
│ │ │ │
│ │ │ │
│ │ │ │
│ │ │ │
│ └─────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
设置布局 #
cpp
// 方式一:直接设置到控件
QWidget *widget = new QWidget;
QVBoxLayout *layout = new QVBoxLayout(widget);
// widget 自动成为 layout 的父对象
// 方式二:调用 setLayout
QWidget *widget = new QWidget;
QVBoxLayout *layout = new QVBoxLayout;
widget->setLayout(layout);
// 方式三:布局嵌套
QVBoxLayout *mainLayout = new QVBoxLayout;
QHBoxLayout *subLayout = new QHBoxLayout;
mainLayout->addLayout(subLayout);
QHBoxLayout 水平布局 #
基本使用 #
cpp
QWidget *widget = new QWidget;
QHBoxLayout *layout = new QHBoxLayout(widget);
// 添加控件
QPushButton *button1 = new QPushButton("Button 1");
QPushButton *button2 = new QPushButton("Button 2");
QPushButton *button3 = new QPushButton("Button 3");
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
widget->show();
text
┌─────────────────────────────────────────────────────────────┐
│ [Button 1] [Button 2] [Button 3] │
└─────────────────────────────────────────────────────────────┘
设置间距和边距 #
cpp
// 设置控件之间的间距
layout->setSpacing(10); // 默认值由系统决定
// 设置边距
layout->setContentsMargins(10, 10, 10, 10); // 左、上、右、下
layout->setContentsMargins(QMargins(10, 10, 10, 10));
// Qt 6 简化设置
layout->setSpacing(10);
添加拉伸因子 #
cpp
// 添加拉伸空间
layout->addStretch(); // 弹性空间
// 带拉伸因子的控件
layout->addWidget(button1, 1); // 拉伸因子为 1
layout->addWidget(button2, 2); // 拉伸因子为 2
// 示例:按钮在右侧
layout->addStretch(); // 左侧填充
layout->addWidget(button1);
layout->addWidget(button2);
text
┌─────────────────────────────────────────────────────────────┐
│ [Button 1] [Button 2]│
└─────────────────────────────────────────────────────────────┘
QVBoxLayout 垂直布局 #
基本使用 #
cpp
QWidget *widget = new QWidget;
QVBoxLayout *layout = new QVBoxLayout(widget);
QPushButton *button1 = new QPushButton("Button 1");
QPushButton *button2 = new QPushButton("Button 2");
QPushButton *button3 = new QPushButton("Button 3");
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
widget->show();
text
┌─────────────────────────────────────────────────────────────┐
│ [Button 1] │
│ [Button 2] │
│ [Button 3] │
└─────────────────────────────────────────────────────────────┘
常见布局模式 #
cpp
// 顶部对齐
layout->addWidget(button1);
layout->addWidget(button2);
layout->addStretch(); // 底部填充
// 底部对齐
layout->addStretch(); // 顶部填充
layout->addWidget(button1);
layout->addWidget(button2);
// 居中对齐
layout->addStretch();
layout->addWidget(button1);
layout->addWidget(button2);
layout->addStretch();
QGridLayout 网格布局 #
基本使用 #
cpp
QWidget *widget = new QWidget;
QGridLayout *layout = new QGridLayout(widget);
// 添加控件到网格
// addWidget(widget, row, column)
layout->addWidget(new QPushButton("1"), 0, 0);
layout->addWidget(new QPushButton("2"), 0, 1);
layout->addWidget(new QPushButton("3"), 1, 0);
layout->addWidget(new QPushButton("4"), 1, 1);
// 跨行跨列
// addWidget(widget, row, column, rowSpan, columnSpan)
layout->addWidget(new QPushButton("5"), 2, 0, 1, 2); // 跨两列
widget->show();
text
┌─────────────────────────────────────────────────────────────┐
│ [1] [2] │
│ [3] [4] │
│ [ 5 ] │
└─────────────────────────────────────────────────────────────┘
设置行列拉伸 #
cpp
// 设置列拉伸因子
layout->setColumnStretch(0, 1); // 第 0 列拉伸因子 1
layout->setColumnStretch(1, 2); // 第 1 列拉伸因子 2
// 设置行拉伸因子
layout->setRowStretch(0, 1);
layout->setRowStretch(1, 2);
// 设置最小行高/列宽
layout->setRowMinimumHeight(0, 50);
layout->setColumnMinimumWidth(0, 100);
计算器示例 #
cpp
QWidget *widget = new QWidget;
QGridLayout *layout = new QGridLayout(widget);
QStringList buttons = {
"7", "8", "9", "/",
"4", "5", "6", "*",
"1", "2", "3", "-",
"0", ".", "=", "+"
};
for (int i = 0; i < buttons.size(); ++i) {
QPushButton *btn = new QPushButton(buttons[i]);
btn->setMinimumSize(60, 60);
layout->addWidget(btn, i / 4, i % 4);
}
widget->show();
QFormLayout 表单布局 #
基本使用 #
cpp
QWidget *widget = new QWidget;
QFormLayout *layout = new QFormLayout(widget);
// 添加行
layout->addRow("Name:", new QLineEdit);
layout->addRow("Email:", new QLineEdit);
layout->addRow("Age:", new QSpinBox);
layout->addRow("", new QPushButton("Submit"));
widget->show();
text
┌─────────────────────────────────────────────────────────────┐
│ Name: [________________] │
│ Email: [________________] │
│ Age: [____↑____] │
│ [Submit] │
└─────────────────────────────────────────────────────────────┘
设置对齐和换行 #
cpp
// 设置标签对齐
layout->setLabelAlignment(Qt::AlignRight | Qt::AlignVCenter);
// 设置字段增长策略
layout->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint);
layout->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
layout->setFieldGrowthPolicy(QFormLayout::AllNonFixedFieldsGrow);
// 设置行换行策略
layout->setRowWrapPolicy(QFormLayout::DontWrapRows);
layout->setRowWrapPolicy(QFormLayout::WrapLongRows);
layout->setRowWrapPolicy(QFormLayout::WrapAllRows);
QStackedLayout 堆栈布局 #
基本使用 #
cpp
QWidget *widget = new QWidget;
QVBoxLayout *mainLayout = new QVBoxLayout(widget);
// 创建导航按钮
QHBoxLayout *navLayout = new QHBoxLayout;
QPushButton *btn1 = new QPushButton("Page 1");
QPushButton *btn2 = new QPushButton("Page 2");
QPushButton *btn3 = new QPushButton("Page 3");
navLayout->addWidget(btn1);
navLayout->addWidget(btn2);
navLayout->addWidget(btn3);
// 创建堆栈布局
QStackedLayout *stackLayout = new QStackedLayout;
stackLayout->addWidget(new QLabel("This is Page 1"));
stackLayout->addWidget(new QLabel("This is Page 2"));
stackLayout->addWidget(new QLabel("This is Page 3"));
// 连接信号
connect(btn1, &QPushButton::clicked, [=]() { stackLayout->setCurrentIndex(0); });
connect(btn2, &QPushButton::clicked, [=]() { stackLayout->setCurrentIndex(1); });
connect(btn3, &QPushButton::clicked, [=]() { stackLayout->setCurrentIndex(2); });
mainLayout->addLayout(navLayout);
mainLayout->addLayout(stackLayout);
widget->show();
切换页面 #
cpp
// 按索引切换
stackLayout->setCurrentIndex(1);
// 按控件切换
QWidget *page = new QWidget;
stackLayout->addWidget(page);
stackLayout->setCurrentWidget(page);
// 获取当前索引
int index = stackLayout->currentIndex();
// 获取页面数量
int count = stackLayout->count();
布局嵌套 #
复杂界面布局 #
cpp
QWidget *widget = new QWidget;
QVBoxLayout *mainLayout = new QVBoxLayout(widget);
// 顶部工具栏
QHBoxLayout *toolbarLayout = new QHBoxLayout;
toolbarLayout->addWidget(new QPushButton("New"));
toolbarLayout->addWidget(new QPushButton("Open"));
toolbarLayout->addWidget(new QPushButton("Save"));
toolbarLayout->addStretch();
// 中间内容区域
QHBoxLayout *contentLayout = new QHBoxLayout;
// 左侧导航
QVBoxLayout *navLayout = new QVBoxLayout;
navLayout->addWidget(new QPushButton("Home"));
navLayout->addWidget(new QPushButton("Settings"));
navLayout->addWidget(new QPushButton("Help"));
navLayout->addStretch();
// 右侧主内容
QVBoxLayout *mainContentLayout = new QVBoxLayout;
mainContentLayout->addWidget(new QTextEdit);
contentLayout->addLayout(navLayout, 1);
contentLayout->addLayout(mainContentLayout, 4);
// 底部状态栏
QHBoxLayout *statusLayout = new QHBoxLayout;
statusLayout->addWidget(new QLabel("Ready"));
statusLayout->addStretch();
statusLayout->addWidget(new QLabel("v1.0"));
mainLayout->addLayout(toolbarLayout);
mainLayout->addLayout(contentLayout);
mainLayout->addLayout(statusLayout);
widget->show();
控件大小策略 #
QSizePolicy #
cpp
// 设置大小策略
widget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
// 水平策略
QSizePolicy::Fixed // 固定大小
QSizePolicy::Minimum // 最小大小,不能更小
QSizePolicy::Maximum // 最大大小,不能更大
QSizePolicy::Preferred // 首选大小,可以伸缩
QSizePolicy::Expanding // 扩展,尽可能大
QSizePolicy::MinimumExpanding // 最小大小,但会扩展
QSizePolicy::Ignored // 忽略大小提示
// 示例
QPushButton *button = new QPushButton("Button");
button->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
// 设置拉伸因子
button->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed, 2));
最小/最大大小 #
cpp
// 设置最小大小
widget->setMinimumSize(100, 50);
widget->setMinimumWidth(100);
widget->setMinimumHeight(50);
// 设置最大大小
widget->setMaximumSize(500, 300);
widget->setMaximumWidth(500);
widget->setMaximumHeight(300);
// 固定大小
widget->setFixedSize(200, 100);
widget->setFixedWidth(200);
widget->setFixedHeight(100);
// 大小提示
QSize hint = widget->sizeHint();
布局调试 #
可视化调试 #
cpp
// 在 Qt Creator 中使用布局预览
// 右键布局 -> 预览
// 使用样式表调试
widget->setStyleSheet(R"(
QWidget {
border: 1px solid red;
}
)");
常见问题 #
cpp
// 问题1:控件没有显示
// 检查:是否设置了布局?控件是否添加到布局?
// 问题2:布局不生效
// 检查:是否在正确的父控件上设置了布局?
// 问题3:控件大小不对
// 检查:大小策略、最小/最大大小设置
// 强制更新布局
layout->update();
widget->updateGeometry();
下一步 #
现在你已经掌握了布局管理,接下来学习 列表与表格,了解如何展示列表和表格数据!
最后更新:2026-03-29