Qt——布局管理器(一)

1.目前GUI开发方式:绝对定位

直接在像素级指定各个组件的位置和大小,但是组建的位置和大小无法自适应父窗口的变化

解决方案:布局管理器,提供相关的类对界面组件进行布局管理

  • 能够自动排列窗口中的界面组件
  • 窗口变化后自动更新界面组件的大小

2.QLayout是Qt中布局管理器的抽象基类

(1)QBoxLayout布局管理器:以水平或垂直的方式管理界面组件

原来的代码:

复制代码
Widget::Widget(QWidget *parent) : QWidget(parent),
    TestBtn1(this), TestBtn2(this), TestBtn3(this), TestBtn4(this)
{
    initControl();
}

void Widget::initControl()
{
    TestBtn1.setText("TestBtn1");
    TestBtn1.move(20, 20);
    TestBtn1.resize(160, 30);

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

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

    TestBtn4.setText("TestBtn4");
    TestBtn4.move(20, 170);
    TestBtn4.resize(160, 30);
}
Widget::~Widget()
{

}

使用QBoxLayout后的代码:

复制代码
Widget::Widget(QWidget *parent) : QWidget(parent),
    TestBtn1(this), TestBtn2(this), TestBtn3(this), TestBtn4(this)
{
    testVBoxLayout();
}

 void Widget::testVBoxLayout()
{
    QVBoxLayout* layout = new QVBoxLayout();

    TestBtn1.setText("TestBtn1");
    TestBtn2.setText("TestBtn2");
    TestBtn3.setText("TestBtn3");
    TestBtn4.setText("TestBtn4");

    layout->addWidget(&TestBtn1);
    layout->addWidget(&TestBtn2);
    layout->addWidget(&TestBtn3);
    layout->addWidget(&TestBtn4);

    setLayout(layout);
}
Widget::~Widget()
{

}

但是该布局策略为:随着窗口放大,按钮的高度不变,只有宽度放大,如何改变呢?

复制代码
Widget::Widget(QWidget *parent) : QWidget(parent),
    TestBtn1(this), TestBtn2(this), TestBtn3(this), TestBtn4(this)
{
    testHBoxLayout();
}

void Widget::testVBoxLayout() //垂直布局
{
    QVBoxLayout* layout = new QVBoxLayout();

    TestBtn1.setText("TestBtn1");
    //让按钮 TestBtn1 在水平和垂直两个方向上,都自动拉伸填满父布局的可用空间。
    TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TestBtn1.setMinimumSize(160,30); //设置按钮最小长度和高度

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

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

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

    layout->setSpacing(30); //设置按钮之间的距离
    layout->addWidget(&TestBtn1);
    layout->addWidget(&TestBtn2);
    layout->addWidget(&TestBtn3);
    layout->addWidget(&TestBtn4);

    setLayout(layout);
}
void Widget::testHBoxLayout() //水平布局
{
    QHBoxLayout* layout = new QHBoxLayout();

    TestBtn1.setText("TestBtn1");
    //让按钮 TestBtn1 在水平和垂直两个方向上,都自动拉伸填满父布局的可用空间。
    TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TestBtn1.setMinimumSize(160,30); //设置按钮最小长度和高度

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

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

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

    layout->setSpacing(30); //设置按钮之间的距离
    layout->addWidget(&TestBtn1);
    layout->addWidget(&TestBtn2);
    layout->addWidget(&TestBtn3);
    layout->addWidget(&TestBtn4);

    setLayout(layout);
}

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

复制代码
void Widget::testVHBoxLayout() //嵌套布局
{
    QHBoxLayout* hlayout1 = new QHBoxLayout();
    QHBoxLayout* hlayout2 = new QHBoxLayout();
    QVBoxLayout* vlayout = new QVBoxLayout();

    TestBtn1.setText("TestBtn1");
    //让按钮 TestBtn1 在水平和垂直两个方向上,都自动拉伸填满父布局的可用空间。
    TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TestBtn1.setMinimumSize(160,30); //设置按钮最小长度和高度

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

    hlayout1->setSpacing(10);
    hlayout1->addWidget(&TestBtn1);
    hlayout1->addWidget(&TestBtn2);

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

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

    hlayout2->setSpacing(10);
    hlayout2->addWidget(&TestBtn3);
    hlayout2->addWidget(&TestBtn4);

    vlayout->setSpacing(10); //设置按钮之间的距离
    vlayout->addLayout(hlayout1);
    vlayout->addLayout(hlayout2);

    setLayout(vlayout);
}

4.布局管理器中的比例系数

  • 默认情况下以等比例的方式更新组件的大小

  • 可以自定义组件大小更新时的比例系数

    void Widget::testVBoxLayout()
    {
    QVBoxLayout* layout = new QVBoxLayout();

    复制代码
      TestBtn1.setText("TestBtn1");
      //让按钮 TestBtn1 在水平和垂直两个方向上,都自动拉伸填满父布局的可用空间。
      TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
      TestBtn1.setMinimumSize(160,30); //设置按钮最小长度和高度
    
      TestBtn2.setText("TestBtn2");
      TestBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
      TestBtn2.setMinimumSize(160,30);
    
      TestBtn3.setText("TestBtn3");
      TestBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
      TestBtn3.setMinimumSize(160,30);
    
      TestBtn4.setText("TestBtn4");
      TestBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
      TestBtn4.setMinimumSize(160,30);
    
      layout->setSpacing(30); //设置按钮之间的距离
      layout->addWidget(&TestBtn1);
      layout->addWidget(&TestBtn2);
      layout->addWidget(&TestBtn3);
      layout->addWidget(&TestBtn4);
      layout->setStretch(0, 1); //定义第0个格子的比例系数是1
      layout->setStretch(1, 1);
      layout->setStretch(2, 2);
      layout->setStretch(3, 2);
    
      setLayout(layout);

    }
    void Widget::testHBoxLayout()
    {
    QHBoxLayout* layout = new QHBoxLayout();

    复制代码
      TestBtn1.setText("TestBtn1");
      //让按钮 TestBtn1 在水平和垂直两个方向上,都自动拉伸填满父布局的可用空间。
      TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
      TestBtn1.setMinimumSize(160,30); //设置按钮最小长度和高度
    
      TestBtn2.setText("TestBtn2");
      TestBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
      TestBtn2.setMinimumSize(160,30);
    
      TestBtn3.setText("TestBtn3");
      TestBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
      TestBtn3.setMinimumSize(160,30);
    
      TestBtn4.setText("TestBtn4");
      TestBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
      TestBtn4.setMinimumSize(160,30);
    
      layout->setSpacing(30); //设置按钮之间的距离
      layout->addWidget(&TestBtn1);
      layout->addWidget(&TestBtn2);
      layout->addWidget(&TestBtn3);
      layout->addWidget(&TestBtn4);
      layout->setStretchFactor(&TestBtn1, 1); //将TestBtn1设置系数为1
      layout->setStretchFactor(&TestBtn2, 2);
      layout->setStretchFactor(&TestBtn3, 1);
      layout->setStretchFactor(&TestBtn4, 3);
    
      setLayout(layout);

    }

注意:组件的初始大小是独立于布局管理器设置的,因此不能保证组件的大小始终符合比例系数的设置,例如上述代码中设置了按钮的初始大小,所以一开始的时候,比例对应不是设置的系数

5.QGridLayout布局管理器,以网格(二维矩阵)的方式管理界面组件

复制代码
void Widget::testGridLayout1()
{
    QGridLayout* layout = new QGridLayout();

    TestBtn1.setText("TestBtn1");
    //让按钮 TestBtn1 在水平和垂直两个方向上,都自动拉伸填满父布局的可用空间。
    TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TestBtn1.setMinimumSize(160,30); //设置按钮最小长度和高度

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

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

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

    layout->setSpacing(10);
    layout->addWidget(&TestBtn1, 0, 0); //将TestBtn1按钮放在(0,0)位置
    layout->addWidget(&TestBtn2, 0, 1);
    layout->addWidget(&TestBtn3, 1, 0);
    layout->addWidget(&TestBtn4, 1, 1);
    
    layout->setRowStretch(0, 1); //设置第0行的比例因子为1
    layout->setRowStretch(1, 3);
    
    layout->setColumnStretch(0, 1); //设置第0列的比例因子为1
    layout->setColumnStretch(1, 3);
    setLayout(layout);
}

void Widget::testGridLayout2()
{
    QGridLayout* layout = new QGridLayout();
    
    TestBtn1.setText("TestBtn1");
    //让按钮 TestBtn1 在水平和垂直两个方向上,都自动拉伸填满父布局的可用空间。
    TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TestBtn1.setMinimumSize(160,30); //设置按钮最小长度和高度
    
    TestBtn2.setText("TestBtn2");
    TestBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TestBtn2.setMinimumSize(160,30);
    
    TestBtn3.setText("TestBtn3");
    TestBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TestBtn3.setMinimumSize(160,30);
    
    TestBtn4.setText("TestBtn4");
    TestBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TestBtn4.setMinimumSize(160,30);
    
    layout->setSpacing(10);
    layout->addWidget(&TestBtn1, 0, 0, 2, 1); //将TestBtn1按钮放在(0,0)位置,并且占用2行1列
    layout->addWidget(&TestBtn2, 0, 1, 2, 1);
    layout->addWidget(&TestBtn3, 2, 0, 1, 2);
    layout->addWidget(&TestBtn4, 3, 0, 1, 2);
    
    \
    setLayout(layout);
}
相关推荐
小小前端仔LC几秒前
Node.js + LangChain + React:搭建个人知识库(六)- “吃什么”项目实战:从700+菜谱入库到Taro H5端JSON渲染
前端·后端
晓131317 分钟前
【Cocos Creator 3.x】篇——第二章 入门
前端·javascript·游戏引擎
程序员黑豆25 分钟前
AI全栈开发之Java:怎么配置Java环境变量
前端·后端·ai编程
xiaofeichaichai1 小时前
React Hooks
前端·javascript·react.js
问心无愧05131 小时前
ctf show web入门110
前端·笔记
拉拉肥_King1 小时前
Vue 3 主题切换深度解析:从炫酷动画到零闪烁方案
前端·vue.js
excel1 小时前
为什么 Pinia + localForage 持久化后,页面初始化拿不到数据?
前端
雨雨雨雨雨别下啦1 小时前
vant介绍
前端
小小小小宇1 小时前
大模型失忆问题探讨
前端
wordbaby1 小时前
rn-cross-calendar:一个兼容 React 18/19、RN/RNOH 的跨平台日历组件
前端·react native·harmonyos