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);
}
相关推荐
peak_chan2 小时前
通过vue-virtual-scroller封装虚拟滚动el-select
前端·javascript·vue.js
小李子呢02112 小时前
前端八股Vue(7)---computed计算属性和watch侦听器
前端·javascript·vue.js
CCIE-Yasuo2 小时前
Win11-Microsoft Edge使用起来CPU飙升以及卡顿问题解决
前端·microsoft·edge·排故
AlanW3 小时前
QT 信号槽内部实现原理深度解析
qt
是江迪呀3 小时前
实时看大家都在干嘛?我靠一行监听函数,做了个轻互动小程序
前端·微信小程序
A.A呐3 小时前
【QT第五章】系统相关
开发语言·qt
QCzblack3 小时前
BugKu BUUCTF ——Reverse
java·前端·数据库
gwjcloud3 小时前
基于linux下docker部署前端vue项目
前端·javascript·vue.js
小李子呢02113 小时前
前端八股CSS(1)---响应式布局的方法
前端·css