Qt之布局Layout的应用

一、简述

前天群里有个小伙伴说对Qt中的布局很困惑,想让我写一篇关于布局的文章,今天就应这位同学的要求,先简单介绍一下Qt中的布局。

对于刚接触Qt的小伙伴可能对Qt中的各种布局以及各种参数云里雾里,后面将会对布局进行一一介绍。其实刚开始学Qt的时候对布局也很头疼,不知道如何下手,还是要多看文档,多看(写)代码,看的多了,写的多了,自然也就熟了。这就好比是闯关游戏,需要打怪升级,突破一个一个关卡,最终走向胜利。不过这一路走来必定是坎坷万分。

二、布局介绍

说到布局,最常用的想必是QHBoxLayoutQVBoxLayout这两个了,所以今天就以这两个为主角。想要搞懂布局,就先要从这两个简单的入手。不过真要说把布局完完整整地介绍完那还不如直接看文档了,最详细,不过文档有时候只有文字介绍,没有详细的代码说明,以及运行效果图啥的,所以对于新手来说,光看文档可能有点困难,对于有个一段时间学习之后看文档效果还是非常好的。

我们看到Qt文档中对于QVBoxLayout的介绍,用于垂直排列部件(widget),至于什么是box layout 请听下回分解。下面也给了一个简单的例子,将5个按钮垂直排列在一个widget中。

这里写图片描述 这里写图片描述

我们再来看一下下面这张图。我们看到QVBoxLayout继承于QBoxLayout,而QBoxLayout继承于QLayout、而QLayout继承于QObject and QLayoutItem。

同时,QVBoxLayout除了构造和析构,其他的方法都是从父类中继承而来(见下图)。

这里写图片描述

所以我们跟踪一下源码,就可以立即知道,其实QVBoxLayout、QHBoxLayout什么也没干,真正实现其实在QBoxLayout中。

这里写图片描述


仔细看下图两个标注部分,第一个构造方法与第二个构造方法的唯一区别也就是多了个父指针,那多了个父指针有什么用呢,我们看到第二个红色矩形标注部分,“You must add it to another layout”,也就是如果创建QVBoxLayout 时没有传入父指针,那么就必须将这个layout添加到另一个layout中。

添加的方法有两种方式,一种是已经创建好了一个layoutA,然后新创建一个layoutB,将layoutB添加到layoutA中,即:

代码A :

    QVBoxLayout layoutA;
    QVBoxLayout layoutB;
    layoutA.addItem(&layoutB);

另一种则是直接给一个widget设置一个layout,即:

代码B :

    QWidget widget;
    QVBoxLayout layout;
    widget->setLayout(&layout);

那我们如果用第一种构造方法,传入一个父指针是不是就不用 add it to another layout,答案是肯定的,效果类似于上面的代码,即:

代码C :

    QWidget widget;
    QVBoxLayout layout(&widget); // 相当于 widget->setLayout(&layout);

同时,第一种构造方法中提到创建一个 top-level vertical box(顶级的垂直布局)。而第二种构造方法创建的对象,通过代码B也能实现同样的效果(即代码C)

Constructs a new top-level vertical box with parent \a parent

这里写图片描述

上面我们看了QVBoxLayout(垂直布局),而QHBoxLayout(水平布局)其实是类似的,只不过构造中的一个参数不同。

这里写图片描述

这里写图片描述

QVBoxLayout 和 QHBoxLayout的不同还是在QBoxLayout中进行了处理,我们看到下图中定义的枚举Direction,也就是在这里指定不同的枚举值对box layout 进行不同的排列。(详情将在下一篇中)
这里写图片描述


特别注意:

这里我们要注意一下QWidget::setLayout方法,下面标注部分提到:

如果这个widget之前已经设置了一个layout, 现在再次调用setLayout方法设置新的layout,那么就必须删除之前的那个布局(通过layout()方法获得)。

如果这个layout之前已经被设置在一个widgetA上,那么现在如果widgetB调用setLayout方法,传入当前这个layout,那么widgetA上的layout将会转移给widgetB,也就是说widgetA布局失效,将在widgetB上生效。

这里写图片描述

代码D :

    m_widget = new MyWidget();

    // 创建两个按钮;
    QPushButton* buttonA = new QPushButton;
    buttonA->setText("ButtonA");
    QPushButton* buttonB = new QPushButton;
    buttonB->setText("ButtonB");

    // 垂直布局;
    QVBoxLayout *layoutA = new QVBoxLayout;
    layoutA->addWidget(buttonA);
    layoutA->addWidget(buttonB);

    // 水平布局;
    QHBoxLayout *layoutB = new QHBoxLayout;
    layoutB->addWidget(buttonA);
    layoutB->addWidget(buttonB);

    // 设置垂直布局A;
    m_widget->setLayout(layoutA);


    // 删除老的布局;
    QLayout* oldLayout = m_widget->layout();
    delete oldLayout;
    // 设置新的水平布局B;
    m_widget->setLayout(layoutB);

测试效果图:
我们发现删除老布局之后,新布局设置成功

这里写图片描述

注释掉上面倒数第二行代码(delete oldLayout;),效果图:
我们发现未删除老布局,新布局未设置成功

这里写图片描述


综上,我们看到如果不删除旧的布局,新的布局设置之后是不会生效的。所以在设置新的布局之前,必须删除旧布局。


对于Qt中的布局使用不是一下两下能讲完,因为涉及到了很多知识点,需要逐个击破,同时也需要花足够的时间查阅帮助文档以及源码。后面会定期讲述更多布局的内容与应用,希望大家多多支持。

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值