文章目录
1. QVBoxLayout
QVBoxLayout
表示垂直布局管理器
1.1 常用属性
属性 | 类型 | 读写性 | 说明 | 取值范围 |
---|---|---|---|---|
layoutLeftMargin | int | 读写 | 布局的左侧边距,即布局与父容器左侧边缘之间的距离。通过设置该属性,可以控制布局在父容器中左侧的留白大小。 | 非负整数,单位为像素。值为 0 表示没有边距。 |
layoutRightMargin | int | 读写 | 布局的右侧边距,即布局与父容器右侧边缘之间的距离。用于控制布局在父容器中右侧的留白大小。 | 非负整数,单位为像素。值为 0 表示没有边距。 |
layoutTopMargin | int | 读写 | 布局的上方边距,即布局与父容器上侧边缘之间的距离。可调整布局在父容器中上方的留白大小。 | 非负整数,单位为像素。值为 0 表示没有边距。 |
layoutBottomMargin | int | 读写 | 布局的下方边距,即布局与父容器下侧边缘之间的距离。用于设置布局在父容器中下方的留白大小。 | 非负整数,单位为像素。值为 0 表示没有边距。 |
layoutSpacing | int | 读写 | 布局中相邻元素之间的间距,即垂直排列的子控件之间的垂直距离。能调整子控件之间的疏密程度。 | 非负整数,单位为像素。值为 0 表示子控件紧密排列。 |
1.2 例子1,使用代码创建
创建5个按钮,widget.cpp
如下
Widget::Widget(QWidget* parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QPushButton* bt1 = new QPushButton("One");
QPushButton* bt2 = new QPushButton("Two");
QPushButton* bt3 = new QPushButton("Three");
QPushButton* bt4 = new QPushButton("Four");
QPushButton* bt5 = new QPushButton("Five");
// 创建布局管理器,并将按钮添加进去,如果这里指定了parent为this,就不需要后面的setlayout了
QVBoxLayout* layout = new QVBoxLayout();
layout->addWidget(bt1);
layout->addWidget(bt2);
layout->addWidget(bt3);
layout->addWidget(bt4);
layout->addWidget(bt5);
this->setLayout(layout); // 将一个布局管理器(QLayout 或其派生类的对象)关联到一个 QWidget 上
}
拖动窗口,按钮的位置和大小也会跟着变化
1.3 例子2,使用Qt Designer
先拖入两个Vertical Layout,之后向里面拖入几个控件
运行程序,发现拖动外部的窗口里面的两个Layout不会跟着变化
事实上,一个widget只能设置一个layout布局,观察widget.ui
可以发现这两个layout创建了两个QWidget,所以这两个layout不会跟着外部窗口的变化而变化
2. QHBoxLayout
QHBoxLayout
表示水平布局,属性与QVBoxLayout
类似
2.1 例子1,基础使用
创建3个按钮,widget.cpp
如下
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QPushButton* bt1 = new QPushButton("One");
QPushButton* bt2 = new QPushButton("Two");
QPushButton* bt3 = new QPushButton("Three");
// 创建布局管理器,并将按钮添加进去
QHBoxLayout* layout = new QHBoxLayout(this);
layout->addWidget(bt1);
layout->addWidget(bt2);
layout->addWidget(bt3);
}
运行结果如下
2.2 例子2,嵌套使用
如果我们想实现如下的样式,需要嵌套使用这两种布局
widget.cpp
如下
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QLineEdit* edit1 = new QLineEdit();
QLineEdit* edit2 = new QLineEdit();
QPushButton* bt1 = new QPushButton("One");
QPushButton* bt2 = new QPushButton("Two");
// 垂直布局管理器
QVBoxLayout* v_layout = new QVBoxLayout(this);
v_layout->addWidget(edit1);
v_layout->addWidget(edit2);
// 水平布局管理器
QHBoxLayout* h_layout = new QHBoxLayout();
h_layout->addWidget(bt1);
h_layout->addWidget(bt2);
// 将水平布局管理器添加到垂直布局管理器里
v_layout->addLayout(h_layout);
}
运行结果如下
3. QGridLayout
使用QGridLayout
来模拟网格布局的效果。可以达到m*n这种的网格效果
3.1 常用属性
属性 | 类型 | 读写性 | 说明 | 取值范围 |
---|---|---|---|---|
layoutLeftMargin | int | 读写 | 布局的左侧边距,即布局与父容器左侧边缘之间的距离。它决定了网格布局在父容器中左侧预留的空白区域大小。 | 非负整数,单位为像素,值为 0 表示没有左侧边距。 |
layoutRightMargin | int | 读写 | 布局的右侧边距,即布局与父容器右侧边缘之间的距离。用于控制网格布局在父容器中右侧预留的空白区域大小。 | 非负整数,单位为像素,值为 0 表示没有右侧边距。 |
layoutTopMargin | int | 读写 | 布局的上方边距,即布局与父容器上侧边缘之间的距离。可调整网格布局在父容器中上方预留的空白区域大小。 | 非负整数,单位为像素,值为 0 表示没有上方边距。 |
layoutBottomMargin | int | 读写 | 布局的下方边距,即布局与父容器下侧边缘之间的距离。用于设置网格布局在父容器中下方预留的空白区域大小。 | 非负整数,单位为像素,值为 0 表示没有下方边距。 |
layoutHorizontalSpacing | int | 读写 | 相邻元素之间水平方向的间距,即网格中同一行的相邻列的子控件之间的水平距离。它能控制子控件在水平方向上的疏密程度。 | 非负整数,单位为像素,值为 0 表示水平方向上子控件紧密排列。 |
layoutVerticalSpacing | int | 读写 | 相邻元素之间垂直方向的间距,即网格中同一列的相邻行的子控件之间的垂直距离。可调整子控件在垂直方向上的疏密程度。 | 非负整数,单位为像素,值为 0 表示垂直方向上子控件紧密排列。 |
layoutRowStretch | QList<int> | 读写 | 行方向的拉伸系数,它是一个整数列表,列表中的每个元素对应网格布局中一行的拉伸系数。拉伸系数决定了在布局空间发生变化时,每一行如何分配额外的空间。 | 包含非负整数的列表,列表长度应与网格布局的行数一致。系数越大,该行在空间分配时获得的额外空间越多。 |
layoutColumnStretch | QList<int> | 读写 | 列方向的拉伸系数,是一个整数列表,列表中的每个元素对应网格布局中一列的拉伸系数。用于决定在布局空间变化时,每一列如何分配额外的空间。 | 包含非负整数的列表,列表长度应与网格布局的列数一致。系数越大,该列在空间分配时获得的额外空间越多。 |
3.2 例子1,基础使用
widget.cpp
代码如下
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->resize(400, 300);
// 创建按钮
QPushButton* bt1 = new QPushButton("One");
QPushButton* bt2 = new QPushButton("Two");
QPushButton* bt3 = new QPushButton("Three");
QPushButton* bt4 = new QPushButton("Four");
// 创建布局管理器
QGridLayout* layout = new QGridLayout();
this->setLayout(layout);
layout->addWidget(bt1, 0, 0);
layout->addWidget(bt2, 0, 1);
layout->addWidget(bt3, 1, 0);
layout->addWidget(bt4, 1, 1);
}
成功创建出网格样式
这里的坐标是一个相对位置,比如我们下面设置一个比较夸张的值,bt4
并没有跑到屏幕外面,并不会在bt3
和bt4
之间腾出来很大的空间
layout->addWidget(bt1, 0, 0);
layout->addWidget(bt2, 1, 0);
layout->addWidget(bt3, 2, 0);
layout->addWidget(bt4, 10, 0);
3.3 例子2,设置列的拉伸因子
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QGridLayout* layout = new QGridLayout();
this->setLayout(layout);
QPushButton* bt1 = new QPushButton("One");
QPushButton* bt2 = new QPushButton("Two");
QPushButton* bt3 = new QPushButton("Three");
layout->addWidget(bt1, 0, 0);
layout->addWidget(bt2, 0, 1);
layout->addWidget(bt3, 0, 2);
// 设置拉伸系数, 三个按钮的比例为1:2:3
layout->setColumnStretch(0, 1);
layout->setColumnStretch(1, 2);
layout->setColumnStretch(2, 3);
}
如果某列的拉伸因子为0,表示该列的大小不随着窗口的变化而变化。但如果只有一列,它仍然会随着窗口变化而变化
3.4 例子3,设置行的拉伸因子
搞一个3行2列的表格,widget.cpp
代码如下
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
QGridLayout* layout = new QGridLayout();
this->setLayout(layout);
QPushButton* bt1 = new QPushButton("One");
QPushButton* bt2 = new QPushButton("Two");
QPushButton* bt3 = new QPushButton("Three");
QPushButton* bt4 = new QPushButton("Four");
QPushButton* bt5 = new QPushButton("Five");
QPushButton* bt6 = new QPushButton("Six");
layout->addWidget(bt1, 0, 0);
layout->addWidget(bt2, 0, 1);
layout->addWidget(bt3, 1, 0);
layout->addWidget(bt4, 1, 1);
layout->addWidget(bt5, 2, 0);
layout->addWidget(bt6, 2, 1);
// 设置行元素的宽度比例为1:2:3
layout->setRowStretch(0, 1);
layout->setRowStretch(1, 2);
layout->setRowStretch(2, 3);
}
可以看到,宽度并没有如我们所愿,是1:2:3,而是1:1:1
这是因为QPushButton
的默认布局行为中,宽度是固定的,可以通过void QWidget::setSizePolicy(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical)
来设定某一个空间的拉伸策略。下面是QSizePolicy::Policy
的一些取值
常量 | 值 | 描述 |
---|---|---|
QSizePolicy::Fixed | 0 | QWidget::sizeHint()是唯一可接受的大小,因此部件不能增大或缩小。例如,推送按钮的垂直方向。 |
QSizePolicy::Minimum | GrowFlag | sizeHint()是最小值,且足够。部件可以扩展,但没有更大的必要。例如,推送按钮的水平方向。 它不能小于sizeHint()提供的大小。 |
QSizePolicy::Maximum | ShrinkFlag | sizeHint()是最大值。部件可以无损地缩小,如果其他部件需要空间的话。例如,分隔线。 它不能大于sizeHint()提供的大小。 |
QSizePolicy::Preferred | GrowFlag | ShrinkFlag | sizeHint()是最佳大小,但部件可以缩小且仍然有用。部件可以扩展,但没有大于sizeHint()的必要。QWidget的默认策略。 |
QSizePolicy::Expanding | GrowFlag | ShrinkFlag | ExpandFlag | sizeHint()是合理的大小,但部件可以缩小且仍然有用。部件可以利用额外空间,因此应尽可能多地获取空间。例如,水平滑块的水平方向。 |
QSizePolicy::MinimumExpanding | GrowFlag | ExpandFlag | sizeHint()是最小值,且足够。部件可以利用额外空间,因此应尽可能多地获取空间。例如,水平滑块的水平方向。 |
QSizePolicy::Ignored | ShrinkFlag | GrowFlag | IgnoreFlag | 忽略sizeHint()。部件将尽可能多地获取空间。 |
所以代码改为
Widget::Widget(QWidget* parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 创建布局和按钮
QGridLayout* layout = new QGridLayout();
this->setLayout(layout);
QPushButton* bt1 = new QPushButton("One");
QPushButton* bt2 = new QPushButton("Two");
QPushButton* bt3 = new QPushButton("Three");
QPushButton* bt4 = new QPushButton("Four");
QPushButton* bt5 = new QPushButton("Five");
QPushButton* bt6 = new QPushButton("Six");
// 设置按钮的布局行为
bt1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
bt2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
bt3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
bt4->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
bt5->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
bt6->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
// 将按钮添加进布局中
layout->addWidget(bt1, 0, 0);
layout->addWidget(bt2, 0, 1);
layout->addWidget(bt3, 1, 0);
layout->addWidget(bt4, 1, 1);
layout->addWidget(bt5, 2, 0);
layout->addWidget(bt6, 2, 1);
// 设置行元素的宽度比例为1:2:3
layout->setRowStretch(0, 1);
layout->setRowStretch(1, 2);
layout->setRowStretch(2, 3);
}
这样,按钮的宽度就按照1:2:3的比例缩放了
4. QFormLayout
QFormLayout
用于实现两列表单的布局
4.1 例子1,简单使用
widget.cpp
代码如下
Widget::Widget(QWidget* parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
this->resize(400, 300);
// 创建表单布局和他的成员
QFormLayout* layout = new QFormLayout();
this->setLayout(layout);
QLabel* lable_1 = new QLabel("姓名");
QLabel* lable_2 = new QLabel("电话");
QLabel* lable_3 = new QLabel("住址");
QLineEdit* edit_1 = new QLineEdit();
QLineEdit* edit_2 = new QLineEdit();
QLineEdit* edit_3 = new QLineEdit();
// 添加一行
layout->addRow(lable_1, edit_1);
layout->addRow(lable_2, edit_2);
layout->addRow(lable_3, edit_3);
}
运行结果如下
5. QSpacerItem
QSpacerItem
用于在控件之间,添加一段空白
5.1 例子1,简单使用
widget.cpp
代码如下
Widget::Widget(QWidget* parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
// 创建布局和按钮
QHBoxLayout* layout = new QHBoxLayout();
this->setLayout(layout);
QPushButton* bt1 = new QPushButton("One");
QPushButton* bt2 = new QPushButton("Two");
// 创建一个QSpacerItem
QSpacerItem* spacer = new QSpacerItem(100, 20);
// 添加QSpacerItem
layout->addSpacerItem(spacer);
layout->addWidget(bt1);
layout->addSpacerItem(spacer);
layout->addWidget(bt2);
layout->addSpacerItem(spacer);
}
运行结果如下,可以看到,QSpacerItem
把两个按钮“撑开“了,就像弹簧一样