Qt_布局管理器

目录

1、QVBoxLayout垂直布局

[1.1 QVBoxLayout的使用](#1.1 QVBoxLayout的使用)

[1.2 多个布局管理器](#1.2 多个布局管理器)

2、QHBoxLayout水平布局

[2.1 QHBoxLayout的使用](#2.1 QHBoxLayout的使用)

[2.2 嵌套的Layout](#2.2 嵌套的Layout)

3、QGridLayout网格布局

[3.1 QGridLayout的使用](#3.1 QGridLayout的使用)

[3.2 设置控件大小比例](#3.2 设置控件大小比例)

4、QFormLayout

[4.1 QFormLayout的使用](#4.1 QFormLayout的使用)

5、QSpacerItem

[5.1 QSpacerItem的使用](#5.1 QSpacerItem的使用)

结语


前言:

使用Qt时,在没有布局管理器(Layout)概念之前,在界面上创建控件都是用"绝对定位"来设置的,即调用setGeometry或move函数摆放,或者直接在ui文件中对控件进行手动的摆放,这些方式都会导致界面上的控件摆放存在偏差,影响整体美观。因此引入布局管理器机制,将界面上的控件都直接放到布局管理器下,布局管理器会自动对这些控件进行位置大小的调整,让整个界面看起来更加规整。

1、QVBoxLayout垂直布局

QVBoxLayout表示垂直布局管理器,他也是一个控件,只不过该控件的作用是对内部的其他控件进行规整摆放。QVBoxLayout属性介绍如下:

|--------------------|-----------|
| layoutLeftMargin | 左侧边距 |
| layoutRightMargin | 右侧边距 |
| layoutTopMargin | 上方边距 |
| layoutBottomMargin | 下方边距 |
| layoutSpacing | 相邻元素之间的间距 |

与QVBoxLayout相关的常用接口:

|----------------------|--------------------------------|
| addWidget(QWidget*) | 把控件添加到布局管理器中 |
| setLayout(QLayout*) | 是QWidget的接口,用于将布局管理器设置到widget下 |

1.1 QVBoxLayout的使用

创建一个QVBoxLayout和三个按钮控件,将三个按钮控件放到该QVBoxLayout下,观察生成后的界面,代码如下:

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QVBoxLayout>
#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QVBoxLayout* qv = new QVBoxLayout();//创建垂直布局管理器

    //创建三个按钮
    QPushButton* qp1 = new QPushButton("按钮1");
    QPushButton* qp2 = new QPushButton("按钮2");
    QPushButton* qp3 = new QPushButton("按钮3");

    //将三个按钮放到管理器下
    qv->addWidget(qp1);
    qv->addWidget(qp2);
    qv->addWidget(qp3);

    //将管理器设置到当前widge下
    this->setLayout(qv);

}

Widget::~Widget()
{
    delete ui;
}

运行结果:

从结果可以发现三个按钮规章有序的显示在界面上,并且对widget界面进行拉伸时,这三个按钮也会跟着拉伸的比例变化,如果这三个按钮直接放到widget界面上,则按钮尺寸不会随着widget界面的尺寸变化而变化。能够实现这个效果的原因是布局管理器作用在widget上,换句话说,一个widget只能有一个布局管理器并且布局管理器就是widget本身,所以对widget界面进行尺寸拉伸时,实际上就是对布局管理器做拉伸,进而导致布局管理器里的控件也跟着拉伸了。

1.2 多个布局管理器

虽然一个widget下只能有一个布局管理器,但是可以通过ui文件中界面创建的方式在一个widget下生成多个布局管理器,操作如下:

但是在运行程序后,发现对最终的界面进行拖拽则无法影响界面上的按钮,如下图:

原因是通过ui文件手动式创建的Layout,实际上是先创建了一个widget,然后再将创建的Layout放到该widget下,所以上述界面中有3个widget,而我们拖拽的是最外层的widget尺寸,不会影响里面两个widget的尺寸,也就不会影响Layout里的按钮的尺寸了。

2、QHBoxLayout水平布局

QHBoxLayout表示水平布局管理器,他的作用和QVBoxLayout是一样的,不过他是在水平方向摆放控件的,QHBoxLayout效果图如下:

QHBoxLayout属性以及常用接口都和QVBoxLayout一样,因此这里就不再介绍了。

2.1 QHBoxLayout的使用

创建一个QHBoxLayout和三个按钮控件,将三个按钮控件放到该QHBoxLayout下,观察生成后的界面,代码如下:

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QHBoxLayout>
#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //创建水平布局管理器
    QHBoxLayout* qh = new QHBoxLayout();

    //创建三个按钮
    QPushButton* q1 = new QPushButton("按钮1");
    QPushButton* q2 = new QPushButton("按钮2");
    QPushButton* q3 = new QPushButton("按钮3");

    //将按钮添加到管理器中
    qh->addWidget(q1);
    qh->addWidget(q2);
    qh->addWidget(q3);

    //将管理器设置进当前widget中
    this->setLayout(qh);
}

Widget::~Widget()
{
    delete ui;
}

运行结果:

2.2 嵌套的Layout

在上述水平布局管理中添加一个垂直布局管理器,观察最终的现象,代码如下:

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QHBoxLayout>
#include <QPushButton>
#include <QVBoxLayout>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //创建水平布局管理器
    QHBoxLayout* qh = new QHBoxLayout();

    //创建三个按钮
    QPushButton* q1 = new QPushButton("按钮1");
    QPushButton* q2 = new QPushButton("按钮2");
    QPushButton* q3 = new QPushButton("按钮3");

    //将按钮添加到管理器中
    qh->addWidget(q1);
    qh->addWidget(q2);
    qh->addWidget(q3);

    //将管理器设置进当前widget中
    this->setLayout(qh);

    //创建小Layout-垂直管理器
    QVBoxLayout* qh1 = new QVBoxLayout();

    //创建三个按钮
    QPushButton* q4 = new QPushButton("按钮4");
    QPushButton* q5 = new QPushButton("按钮5");
    QPushButton* q6 = new QPushButton("按钮6");

    //将按钮添加到小的垂直管理器中
    qh1->addWidget(q4);
    qh1->addWidget(q5);
    qh1->addWidget(q6);

    //将小垂直管理器添加到水平管理器中
    qh->addLayout(qh1);

}

Widget::~Widget()
{
    delete ui;
}

运行结果:

从上述的例子中可以总结一点:垂直布局管理器的控件添加方式是从下往上式的添加,而水平布局管理器是从右往左式的添加控件。

3、QGridLayout网格布局

QGridLayout表示网格布局,通俗来说就是水平和垂直布局的结合版,就如同一个二维数组,内部的控件就是数值上的元素。QGridLayout属性相比于上述两个控件的区别是:

|-------------------------|---------------|
| layoutHorizontalSpacing | 相邻元素之间⽔平⽅向的间距 |
| layoutVerticalSpacing | 相邻元素之间垂直⽅向的间距 |
| layoutRowStretch | ⾏⽅向的拉伸系数 |
| layoutColumnStretch | 列⽅向的拉伸系数 |

QGridLayout的常用接口和上述两个控件也几乎相同。

3.1 QGridLayout的使用

创建一个QGridLayout和四个按钮控件,将这四个按钮控件放到QGridLayout下,观察生成的界面,代码如下:

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QGridLayout>
#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //创建QGridLayout
    QGridLayout* qg = new QGridLayout();

    //创建四个按钮
    QPushButton* p1 = new QPushButton("按钮1");
    QPushButton* p2 = new QPushButton("按钮2");
    QPushButton* p3 = new QPushButton("按钮3");
    QPushButton* p4 = new QPushButton("按钮4");

    //将按钮添加到QGridLayout中,注意表明出坐标
    qg->addWidget(p1,0,0);
    qg->addWidget(p2,0,1);
    qg->addWidget(p3,1,0);
    qg->addWidget(p4,1,1);

    this->setLayout(qg);

}

Widget::~Widget()
{
    delete ui;
}

运行结果:

可以从结果看到,界面上既能完成垂直布局,又能完成水平布局。

3.2 设置控件大小比例

在QGridLayout中,可以设置以行、列为单位设置控件的拉伸系数,比如调用函数setColumnStretch就是设置列上所有控件的拉伸系数,调用函数setRowStretch就是设置行上所有控件的拉伸系数。注意设置拉伸系数不等于直接设置尺寸,拉伸系数表示与当前单位与其他单位的长度比例。例子如下:

①设置列拉伸(水平方向拉伸控件):

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QGridLayout>
#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //创建QGridLayout
    QGridLayout* qg = new QGridLayout();

    //创建四个按钮
    QPushButton* p1 = new QPushButton("按钮1");
    QPushButton* p2 = new QPushButton("按钮2");
    QPushButton* p3 = new QPushButton("按钮3");
    QPushButton* p4 = new QPushButton("按钮4");

    //将按钮添加到QGridLayout中,注意表明出坐标
    qg->addWidget(p1,0,0);
    qg->addWidget(p2,0,1);
    qg->addWidget(p3,1,0);
    qg->addWidget(p4,1,1);

    this->setLayout(qg);

    qg->setColumnStretch(0,1);//设置该列的拉伸系数是1
    qg->setColumnStretch(1,3);//设置该列的拉伸系数是3
    //则该第1列的长度是第0列的三倍
}

Widget::~Widget()
{
    delete ui;
}

运行结果:

结果是第1列的长度是第0列的三倍。


②设置列拉伸(垂直方向拉伸控件):

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QGridLayout>
#include <QPushButton>
#include <QSizePolicy>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //创建QGridLayout
    QGridLayout* qg = new QGridLayout();

    //创建四个按钮
    QPushButton* p1 = new QPushButton("按钮1");
    QPushButton* p2 = new QPushButton("按钮2");
    QPushButton* p3 = new QPushButton("按钮3");
    QPushButton* p4 = new QPushButton("按钮4");
    //因为每个按钮的垂直尺寸是固定的,因此要手动将按钮的垂直属性设置为拓展,目的是方便观察
    p1->setSizePolicy(QSizePolicy::Ignored,QSizePolicy::Expanding);
    p2->setSizePolicy(QSizePolicy::Ignored,QSizePolicy::Expanding);
    p3->setSizePolicy(QSizePolicy::Ignored,QSizePolicy::Expanding);
    p4->setSizePolicy(QSizePolicy::Ignored,QSizePolicy::Expanding);

    //将按钮添加到QGridLayout中,注意表明出坐标
    qg->addWidget(p1,0,0);
    qg->addWidget(p2,0,1);
    qg->addWidget(p3,1,0);
    qg->addWidget(p4,1,1);

    this->setLayout(qg);

    qg->setRowStretch(0,1);//设置该行的拉伸系数是1
    qg->setRowStretch(1,3);//设置该行的拉伸系数是3
    //则该第1行的长度是第0行的三倍
}

Widget::~Widget()
{
    delete ui;
}

运行结果:

4、QFormLayout

QFormLayout表示表单布局,QFormLayout的功能就比较单一了,他是专门实现只有两列的表单,可以看成是QGridLayout的一个分支控件,因此QFormLayout的属性和QGridLayout几乎一样,只是QFormLayout的添加控件接口为addRow,该接口介绍如下:

cpp 复制代码
void addRow(QWidget *label, QWidget *field);
// 第⼀个控件固定是QLabel, 第⼆个控件可以是任意控件
// 如果把第⼀个参数填写为NULL, 则第一列什么都不显⽰,但是第二个参数不能为空

4.1 QFormLayout的使用

QFormLayout常用于填写信息的场景, 因此模拟一个信息表单,首先创建一个QFormLayout ,和三个QLabel以及三个QLineEdit,实现代码如下:

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QFormLayout>
#include <QLineEdit>
#include <QLabel>
#include <QPushButton>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //创建QFormLayout
    QFormLayout* qf = new QFormLayout;

    //创建三对QLabel和QLineEdit
    QLabel* q1 = new QLabel("姓名");
    QLabel* q2 = new QLabel("电话");
    QLabel* q3 = new QLabel("地址");

    QLineEdit* ql1 = new QLineEdit;
    QLineEdit* ql2 = new QLineEdit;
    QLineEdit* ql3 = new QLineEdit;

    //创建提交按钮
    QPushButton* qp = new QPushButton("提交");

    //将上述控件添加到QFormLayout中
    qf->addRow(q1,ql1);
    qf->addRow(q2,ql2);
    qf->addRow(q3,ql3);
    qf->addRow(nullptr,qp);

    this->setLayout(qf);
}

Widget::~Widget()
{
    delete ui;
}

运行结果:

5、QSpacerItem

QSpacerItem表示一段空白,他的作用是在使⽤布局管理器的时候,可能需要在控件之间添加⼀段空⽩,这时候就可以用QSpacerItem了。QSpacerItem属性介绍如下:

|--------|-----------------------------|
| width | QSpacerItem的 宽度 |
| height | QSpacerItem的 ⾼度 |
| hData | 拉伸时,⽔平⽅向的 sizePolicy 的布局设置 |
| vData | 拉伸时, 垂直⽅向的 sizePolicy 的布局设置 |

5.1 QSpacerItem的使用

创建一个布局管理器,和两个按钮控件以及一个QSpacerItem,观察没有QSpacerItem的界面和有QSpacerItem的界面的区别,代码如下:

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QPushButton>
#include <QHBoxLayout>
#include <QSpacerItem>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //创建一个布局管理器(水平或垂直都行)
    QHBoxLayout* qh = new QHBoxLayout();

    //创建两个按钮
    QPushButton* qp1 = new QPushButton("按钮1");
    QPushButton* qp2 = new QPushButton("按钮2");

    //创建QSpacerItem
    QSpacerItem* qs = new QSpacerItem(100,1);//初始化长、宽

    //将按钮放入布局管理器中
    qh->addWidget(qp1);
    qh->addSpacerItem(qs);
    qh->addWidget(qp2);

    this->setLayout(qh);
}

Widget::~Widget()
{
    delete ui;
}

测试结果:

结语

以上就是关于布局管理器的讲解,布局管理器整体使用难度不高,但他却是Qt开发中较为重要的一个控件,因为他保证了界面的规整度,同时也方便了开发者对控件规划的位置计算。

最后如果本文有遗漏或者有误的地方欢迎大家在评论区补充,谢谢大家!!

相关推荐
Zevalin爱灰灰12 分钟前
Matlab simulink建模与仿真 第十六章(用户定义函数库)
开发语言·matlab
Zevalin爱灰灰18 分钟前
Matlab simulink建模与仿真 第十四章(信号输出库)
开发语言·matlab
汇匠源41 分钟前
小程序服务零工市场
java·大数据·开发语言·小程序·团队开发·零工市场·零工市场小程序
larryyu_cs1 小时前
CF1494F Delete The Edges 题解
c++·算法·图论
王俊山IT1 小时前
C++学习笔记----7、使用类与对象获得高性能(二)---- 理解对象生命周期(7)
开发语言·c++·笔记·学习
弘毅_Hao2 小时前
Qt 构建目录
qt·构建目录
BUG制造机.2 小时前
计算机网络 --- Socket 编程
服务器·c++·计算机网络
tpoog2 小时前
[Linux]自定义shell详解
linux·运维·服务器·数据库·c++
咕咕吖2 小时前
插入排序详解
数据结构·c++·算法
luthane2 小时前
python 实现bailey borwein plouffe算法
开发语言·python·算法