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