一、存在的问题

目前GUI开发方式:绝对定位
直接在像素级指定各个组件的位置和大小

void QWidget::move(int x,int y)
void QWidger::resize(int w,int h)

问题:
组件的位置和大小无法自使用父窗口的变化

二、布局管理器

解决方案:布局管理器
提供相关的类对界面组件进行布局管理
能够自动排列窗口中的界面组件
窗口变化后自动更新界面组件的大小

QLayout是Qt中布局管理器的抽象基类
通过继承QLayout实现了功能各异且互补的布局管理器
Qt中可以根据需要自定义布局管理器
布局管理器不是界面组件,而是界面部件的定位策略
image.png

QBoxLayout布局管理器

以水平或者垂直的方式管理界面组件
image.png

image.png

三、编程实验 22-1.pro QBoxLayout

#include "Widget.h"
#include <QVBoxLayout>


Widget::Widget(QWidget *parent) : QWidget(parent),
    TestBtn1(this), TestBtn2(this), TestBtn3(this), TestBtn4(this)
{
    //initControl();

    testHBoxLayout();
   // testVBoxLayout();
}

void Widget::testVBoxLayout()  //垂直布局管理器
{
    QVBoxLayout* layout = new QVBoxLayout();  //定义垂直布局管理器

    TestBtn1.setText("Test Button 1");
    TestBtn1.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);//水平垂直都是可扩展的
    TestBtn1.setMinimumSize(160,30);//定义窗口大小

    TestBtn2.setText("Test Button 2");
    TestBtn2.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    TestBtn2.setMinimumSize(160,30);

    TestBtn3.setText("Test Button 3");
    TestBtn3.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    TestBtn3.setMinimumSize(160,30);

    TestBtn4.setText("Test Button 4");
    TestBtn4.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    TestBtn4.setMinimumSize(160,30);

    layout->setSpacing(30); //设置空间间隔为30个像素
    layout->addWidget(&TestBtn1); //告诉布局管理器管理的界面组件有那些
    layout->addWidget(&TestBtn2);
    layout->addWidget(&TestBtn3);
    layout->addWidget(&TestBtn4);
    setLayout(layout);//告诉窗口请布局管理器来管理窗口;
}
void Widget::testHBoxLayout()  //水平布局管理器
{
    QHBoxLayout* layout = new QHBoxLayout();  //定义垂直布局管理器

    TestBtn1.setText("Test Button 1");
    TestBtn1.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);//水平垂直都是可扩展的
    TestBtn1.setMinimumSize(160,30);//定义窗口大小

    TestBtn2.setText("Test Button 2");
    TestBtn2.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    TestBtn2.setMinimumSize(160,30);

    TestBtn3.setText("Test Button 3");
    TestBtn3.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    TestBtn3.setMinimumSize(160,30);

    TestBtn4.setText("Test Button 4");
    TestBtn4.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    TestBtn4.setMinimumSize(160,30);

    layout->setSpacing(30); //设置空间间隔为30个像素
    layout->addWidget(&TestBtn1); //告诉布局管理器管理的界面组件有那些
    layout->addWidget(&TestBtn2);
    layout->addWidget(&TestBtn3);
    layout->addWidget(&TestBtn4);
    setLayout(layout);//告诉窗口请布局管理器来管理窗口;
}
void Widget::initControl()
{
    TestBtn1.setText("Test Button 1");
    TestBtn1.move(20, 20);
    TestBtn1.resize(160, 30);

    TestBtn2.setText("Test Button 2");
    TestBtn2.move(20, 70);
    TestBtn2.resize(160, 30);

    TestBtn3.setText("Test Button 3");
    TestBtn3.move(20, 120);
    TestBtn3.resize(160, 30);

    TestBtn4.setText("Test Button 4");
    TestBtn4.move(20, 170);
    TestBtn4.resize(160, 30);
}

Widget::~Widget()
{
    
}

布局管理器可以相互嵌套,形成更加复杂的布局方式

布局嵌套几乎可以完成所有常用的界面布局
自定义布局类可以达到个性化界面布局的效果

QBoxLayout嵌套实例

image.png
addLayout 是将子布局添加到父布局中

四、编程实验 布局嵌套实例


void Widget::testVHBoxLayout()  //布局嵌套管理器
{
    QHBoxLayout* hlayout1 = new QHBoxLayout();
    QHBoxLayout* hlayout2 = new QHBoxLayout();
    QVBoxLayout* Vlayout = new QVBoxLayout();

    TestBtn1.setText("Test Button 1");
    TestBtn1.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);//水平垂直都是可扩展的
    TestBtn1.setMinimumSize(160,30);//定义窗口大小

    TestBtn2.setText("Test Button 2");
    TestBtn2.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    TestBtn2.setMinimumSize(160,30);
    hlayout1->setSpacing(10);
    hlayout1->addWidget(&TestBtn1);
    hlayout1->addWidget(&TestBtn2);
    TestBtn3.setText("Test Button 3");
    TestBtn3.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    TestBtn3.setMinimumSize(160,30);

    TestBtn4.setText("Test Button 4");
    TestBtn4.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
    TestBtn4.setMinimumSize(160,30);
    hlayout2->setSpacing(10);
    hlayout2->addWidget(&TestBtn3);
    hlayout2->addWidget(&TestBtn4);

    Vlayout->setSpacing(10); //设置空间间隔为10个像素
    Vlayout->addLayout(hlayout1,0); //是将子布局添加到父布局中
    Vlayout->addLayout(hlayout2,0);

    setLayout(Vlayout);//告诉窗口请布局管理器来管理窗口;
}

五、小结

绝对定位的布局方式无法自适应窗口的变化
Qt提供了相关的类对界面组件进行布局管理器
Qt预定义了功能各异且互补的布局管理器
布局管理器能够相互嵌套形成复杂的布局


YingLi
6 声望4 粉丝

From zero to hero.