auther: abinng date: 2026-03-19 15:51
createDate:2026-03-19 15:51
常用布局
QHBoxLayout:水平布局 QVBoxLayout:垂直布局 QGridLayout:网格布局
QFormLayout:表单布局
代码实践
0. 说明一下
这里我们要写代码了,先清晰一下结构
我们在 QtCreator 中创建了 QWidget
程序后,会有四个主要文件:main.cpp, widget.h, widget.cpp, widget.ui
当我们用鼠标点的方式设计了 widget.ui
时,还会临时生成一个 ui_widget.h ,在
widget.cpp 中的构造函数内部有一个
ui->setupUi 用 Ctrl + 左键
的方式就可以定位到 ui_widget.h 中
首先 main.cpp 中:
1 2 3 4 5 6 7 8 9 10
| #include "widget.h" #include <QApplication>
int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.show(); return a.exec(); }
|
用 w.show() 主要是为了让我们自定义的 ui 显示出来
widget.h 中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| #ifndef WIDGET_H #define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACE
class Widget : public QWidget { Q_OBJECT
public: Widget(QWidget *parent = nullptr); ~Widget();
private: void show1(); void myshow1(); Ui::Widget *ui; }; #endif
|
这里声明两个函数,同时在 widget.cpp 中定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| #include "widget.h" #include "ui_widget.h" #include <QSizePolicy> #include <QPushButton> #include <QHBoxLayout> #include <QVBoxLayout> #include <QGroupBox> #include <QGridLayout> #include <QComboBox> #include <QFormLayout> #include <QLabel> #include <QLineEdit>
Widget::Widget(QWidget *parent) : QWidget(parent) , ui(new Ui::Widget) { ui->setupUi(this); myshow1(); }
Widget::~Widget() { delete ui; }
void Widget::myshow1() { this->setGeometry(50, 100, 450, 400); auto *main_layout = new QHBoxLayout(this); auto *grp = new QGroupBox(this); auto *grp_layout = new QVBoxLayout(grp); QList<QString> btn_names = {"画笔", "橡皮擦", "清空"}; QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); for(const auto &x : std::as_const(btn_names)) { auto *btn = new QPushButton(x, grp); btn->setSizePolicy(sizePolicy); grp_layout->addWidget(btn); } grp_layout->setStretch(0, 0); grp_layout->setStretch(1, 2); grp_layout->setStretch(2, 1); auto *edit = new QTextEdit(this);
main_layout->addWidget(grp); main_layout->addWidget(edit); main_layout->setStretch(0, 1); main_layout->setStretch(1, 2); }
|
注意在构造函数中调用 myshow1() ,同时将
ui->setupUi(this) 注释,因为这个是调用
ui_widget.h 中的 setupUi 函数,是根据 Ui
设计器自动生成的代码
好,接下来开始写 UI
1. 水平、垂直布局
用代码做出如下效果:

从外往内看:
主布局是水平布局,左边是 GroupBox ,右边是 TextEdie ,左右比例是
1,2
GroupBox 中,三个按钮垂直布局,均为 Expanding
策略,从上到下比例是0,2,1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| void Widget::myshow1() { this->setGeometry(50, 100, 450, 400); auto *main_layout = new QHBoxLayout(this); auto *grp = new QGroupBox(this); auto *grp_layout = new QVBoxLayout(grp); QList<QString> btn_names = {"画笔", "橡皮擦", "清空"}; QSizePolicy sizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); for(const auto &x : std::as_const(btn_names)) { auto *btn = new QPushButton(x, grp); btn->setSizePolicy(sizePolicy); grp_layout->addWidget(btn); } grp_layout->setStretch(0, 0); grp_layout->setStretch(1, 2); grp_layout->setStretch(2, 1); auto *edit = new QTextEdit(this);
main_layout->addWidget(grp); main_layout->addWidget(edit); main_layout->setStretch(0, 1); main_layout->setStretch(1, 2); }
|
2. 网格布局
用代码写出以下效果

主布局中一个 GroupBox ,从上到下是 Label, Widget(Label &
ComboBox, 1:2), TextEdit, 两个按钮
第一行标题:Label,邮件发送客户端,居中,占1行两列
第二行一个 Widget,水平布局,占一行两列,左边一个 Label,右边一个
ComboBox,比例 1:2,ComboBox 中包含三个选项
第三行一个 TextEdit,占一行两列
第四行两个按钮
PushButton,均占用一行一列,位置分别是第四行第一列和第四行第二列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
| void Widget::myshow2() { this->setGeometry(50, 100, 450, 400); auto *main_layout = new QHBoxLayout(this); auto *grp = new QGroupBox(this); auto *grp_layout = new QGridLayout(grp); auto *main_label = new QLabel("邮件发送客户端", grp); main_label->setAlignment(Qt::AlignCenter); auto *send_widget = new QWidget(grp); auto *send_widget_layout = new QHBoxLayout(send_widget); auto *sendto_label = new QLabel("发送给:", send_widget); auto *cmbbox = new QComboBox(send_widget); cmbbox->addItem("abinng"); cmbbox->addItem("bbinng"); cmbbox->addItem("cbinng"); send_widget_layout->addWidget(sendto_label); send_widget_layout->addWidget(cmbbox); send_widget_layout->setStretch(0, 1); send_widget_layout->setStretch(1, 2); auto *edit = new QTextEdit(grp); auto *btn1 = new QPushButton("清空", grp); auto *btn2 = new QPushButton("发送", grp); grp_layout->addWidget(main_label, 0, 0, 1, 2); grp_layout->addWidget(send_widget, 1, 0, 1, 2); grp_layout->addWidget(edit, 2, 0, 1, 2); grp_layout->addWidget(btn1, 3, 0, 1, 1); grp_layout->addWidget(btn2, 3, 1, 1, 1);
main_layout->addWidget(grp); }
|
3. 表单布局,伙伴关系
用代码实现以下效果:

主布局中一个 GroupBox ,采用表单布局,从上到下依次是:标题
Label,两组输入组件 (Label & LineEdit),以及两个按钮
PushButton。
第一行标题:Label,登录客户端,居中,占用一行两列(跨两列)。
第二行用户名输入:左边一个 Label(包含快捷键 &n),右边一个
LineEdit,分别占用表单布局的左右两列,且 Label 设为 LineEdit
的伙伴(Buddy)。
第三行密码输入:左边一个 Label(包含快捷键 &p),右边一个
LineEdit,分别占用表单布局的左右两列,且 Label 设为 LineEdit
的伙伴(Buddy)。
第四行一个按钮:PushButton(注册),占用一行两列(跨两列)。
第五行一个按钮:PushButton(登录),占用一行两列(跨两列)。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| void Widget::myshow3() { this->setGeometry(50, 100, 450, 400); auto *main_layout = new QHBoxLayout(this); auto *grp = new QGroupBox(this); auto *grp_layout = new QFormLayout(grp); auto *main_label = new QLabel("登录客户端", grp); main_label->setAlignment(Qt::AlignCenter); auto *username_label = new QLabel("用户名(&n)", grp); auto *username_edit = new QLineEdit(grp); username_label->setBuddy(username_edit); auto *password_label = new QLabel("密码(&p)", grp); auto *password_edit = new QLineEdit(grp); password_label->setBuddy(password_edit); auto *signup_btn = new QPushButton("注册", grp); auto *login_btn = new QPushButton("登录", grp);
grp_layout->addRow(main_label); grp_layout->addRow(username_label, username_edit); grp_layout->addRow(password_label, password_edit); grp_layout->addRow(signup_btn); grp_layout->addRow(login_btn);
main_layout->addWidget(grp); }
|
布局的属性
一个布局有以下几个属性:
- layoutLeftMargin:该布局与外层的左边间隔
- layoutTopMargin:该布局与外层的上方间隔
- layoutRightMargin:该布局与外层的右边间隔
- layoutBottomMargin:该布局与外层的底部间隔
- layoutSpacing:该布局中组件之间的间隔
- layoutStrech:该布局中组件的比例