4、垂直布局 QVBoxLayout:创建垂直排列的表单、布局嵌套实现复杂界面、设置布局权重
垂直布局,说白了就是让控件从上到下排成一列。这是 Qt 里最基础、最常用的布局方式之一。我刚开始学 Qt 的时候,第一个像样的界面就是用 QVBoxLayout 搭出来的。
你想想看,一个登录对话框、一个设置面板、一个信息展示页——这些界面里,大部分控件都是垂直堆叠的。标签在上,输入框在下,按钮在底部。这就是 QVBoxLayout 的典型应用场景。
4.1 快速上手:创建一个垂直排列的表单
我们先从最简单的例子开始。假设你要做一个用户注册表单,从上到下依次是:用户名、密码、确认密码、注册按钮。
// 创建垂直布局
QVBoxLayout *layout = new QVBoxLayout;
// 添加控件
layout->addWidget(new QLabel("用户名:"));
layout->addWidget(new QLineEdit);
layout->addWidget(new QLabel("密码:"));
layout->addWidget(new QLineEdit);
layout->addWidget(new QLabel("确认密码:"));
layout->addWidget(new QLineEdit);
layout->addWidget(new QPushButton("注册"));
// 应用到窗口
QWidget *window = new QWidget;
window->setLayout(layout);
window->show();
嗯,这里要注意:addWidget() 是按添加顺序从上往下排列的。你添加的第一个控件在最上面,最后一个在最下面。
4.2 布局嵌套:用垂直布局实现复杂界面
实际项目中,很少有界面是单纯的垂直排列。更多时候,我们需要把垂直布局和水平布局嵌套起来用。
举个例子,一个典型的设置界面:左边是分类列表,右边是具体设置项。这个结构怎么搭?
我的做法是:先用一个 QHBoxLayout 作为顶层布局,左边放一个 QVBoxLayout(放分类按钮),右边再放一个 QVBoxLayout(放设置项)。
// 顶层水平布局
QHBoxLayout *mainLayout = new QHBoxLayout;
// 左侧:垂直布局,放分类按钮
QVBoxLayout *leftLayout = new QVBoxLayout;
leftLayout->addWidget(new QPushButton("基本设置"));
leftLayout->addWidget(new QPushButton("高级设置"));
leftLayout->addWidget(new QPushButton("关于"));
leftLayout->addStretch(); // 弹簧,把按钮推到顶部
// 右侧:垂直布局,放具体设置项
QVBoxLayout *rightLayout = new QVBoxLayout;
rightLayout->addWidget(new QLabel("基本设置"));
rightLayout->addWidget(new QLineEdit);
rightLayout->addWidget(new QCheckBox("启用通知"));
rightLayout->addStretch();
// 组合
mainLayout->addLayout(leftLayout);
mainLayout->addLayout(rightLayout);
window->setLayout(mainLayout);
你看,布局嵌套其实就是「大布局套小布局」。我做过一个项目,界面嵌套了四层布局,看起来复杂,但拆开来看,每一层都很简单。
4.3 布局权重:用 setStretchFactor 控制比例
这是很多新手容易搞混的地方。布局权重,说白了就是「当空间有多余时,谁多占一点」。
举个例子:一个聊天窗口,上面是消息列表,下面是输入框。你希望消息列表占 3/4,输入框占 1/4。这时候就需要设置拉伸因子。
QVBoxLayout *layout = new QVBoxLayout;
QTextEdit *messageList = new QTextEdit;
QLineEdit *inputBox = new QLineEdit;
layout->addWidget(messageList);
layout->addWidget(inputBox);
// 设置拉伸因子:消息列表占 3,输入框占 1
layout->setStretchFactor(messageList, 3);
layout->setStretchFactor(inputBox, 1);
这样,当窗口大小变化时,消息列表会按比例获得更多空间,输入框保持较小的高度。
还有一种更简洁的写法,直接在 addWidget 时指定拉伸因子:
layout->addWidget(messageList, 3); // 第二个参数就是拉伸因子
layout->addWidget(inputBox, 1);
我个人更推荐这种写法,代码更紧凑,也不容易忘记设置。
4.4 实战:一个完整的垂直布局示例
下面是一个稍微复杂点的例子,结合了布局嵌套和权重设置。这是一个文件下载器的界面:
// 主布局:垂直
QVBoxLayout *mainLayout = new QVBoxLayout;
// 顶部:标题
QLabel *title = new QLabel("文件下载管理器");
title->setAlignment(Qt::AlignCenter);
mainLayout->addWidget(title);
// 中间:下载列表(占大部分空间)
QListWidget *downloadList = new QListWidget;
mainLayout->addWidget(downloadList, 1); // 拉伸因子 1
// 底部:控制区域(水平布局)
QHBoxLayout *controlLayout = new QHBoxLayout;
controlLayout->addWidget(new QPushButton("添加下载"));
controlLayout->addWidget(new QPushButton("暂停"));
controlLayout->addWidget(new QPushButton("删除"));
controlLayout->addStretch(); // 把按钮推到左边
mainLayout->addLayout(controlLayout); // 注意:addLayout 不是 addWidget
// 最底部:进度条
QProgressBar *progressBar = new QProgressBar;
mainLayout->addWidget(progressBar);
window->setLayout(mainLayout);
这个界面里,下载列表占了大部分空间,控制按钮在底部靠左,进度条在最下面。你看,通过合理的布局嵌套和权重分配,一个功能完整的界面就搭出来了。
4.5 关于 QVBoxLayout 的几个实用技巧
| 方法 | 作用 | 我的使用建议 |
|---|---|---|
| addStretch() | 添加弹簧,占据剩余空间 | 常用在列表末尾,把控件推到顶部 |
| insertWidget(index, widget) | 在指定位置插入控件 | 动态添加时很有用,不用重新排序 |
| setSpacing(int) | 设置控件之间的间距 | 默认是 0,我一般设成 6 或 10 |
| setContentsMargins() | 设置布局与窗口边缘的边距 | 默认有边距,有时需要设为 0 |
4.6 知识体系:垂直布局的核心逻辑
下面这张图帮你理清 QVBoxLayout 的知识脉络:
这张图把 QVBoxLayout 的核心知识点分成了四大块:基本用法、布局嵌套、权重控制、间距与边距。你只要把这四块吃透,垂直布局这块就算入门了。
最后说一句:布局这东西,光看文档是学不会的。我建议你打开 Qt Creator,拖几个控件试试,改改权重,调调间距,很快就能找到感觉。
可可精品资料库