Qt 布局之一:布局初探

前言

对于一个完善的软件,布局管理是必不可少的。 无论是想要界面中部件有一个很整齐的排列,还是想要界面能适应窗口的大小变化,都要进行布局管理。Qt 提供了 QLayout 类及其子类来作为布局管理器,它们可以实现常用的布局管理功能。

水平、垂直、网格、表单布局

为窗口提供一个好布局的最佳方式是使用内置的布局管理器:QHBoxLayout、QVBoxLayout、QGridLayout 和 QFormLayout。这些类都派生自 QLayout,QLayout 又派生自 QObject(非 QWidget),布局窗口自动地把子窗口按照它们被构造地顺序进行布局。要生成更复杂的布局,可以在其它布局里面嵌入另一个布局。

(1)QHBoxLayout:把子窗口从左到右排列在一个水平行上。

QWidget *window = new QWidget;
QPushButton *button1 = new QPushButton("One");
QPushButton *button2 = new QPushButton("Two");
QPushButton *button3 = new QPushButton("Three");
QPushButton *button4 = new QPushButton("Four");
QPushButton *button5 = new QPushButton("Five");

QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
layout->addWidget(button4);
layout->addWidget(button5);

window->setLayout(layout);
window->show();

效果如下所示:

这里写图片描述

(2)QVBoxLayout:把子窗口从上到下排列在一个垂直列上。

...
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(button1);
layout->addWidget(button2);
layout->addWidget(button3);
layout->addWidget(button4);
layout->addWidget(button5);
...

使用与 QHBoxLayout 区别不大。效果如下所示:

这里写图片描述

(3)QGridLayout:把子窗口排列在一个二维的网格中,窗口可占据多个单元格。

...
QGridLayout *layout = new QGridLayout;
layout->addWidget(button1, 0, 0);
layout->addWidget(button2, 0, 1);
layout->addWidget(button3, 1, 0, 1, 2);
layout->addWidget(button4, 2, 0);
layout->addWidget(button5, 2, 1);
...

对于 QGridLayout 有点不同,因为需要指定子控件的行和列的位置。第三个 QPushButton 占据 2 列。通过指定 QGridLayout:: addWidget() 的第五个参数为 2 来实现。效果如下所示:

这里写图片描述

(4)QFormLayout:把子窗口按照 “标签-输入框” 的形式排列在两列。

QWidget *window = new QWidget;
QPushButton *button1 = new QPushButton("One");
QLineEdit *lineEdit1 = new QLineEdit();
QPushButton *button2 = new QPushButton("Two");
QLineEdit *lineEdit2 = new QLineEdit();
QPushButton *button3 = new QPushButton("Three");
QLineEdit *lineEdit3 = new QLineEdit();

QFormLayout *layout = new QFormLayout;
layout->addRow(button1, lineEdit1);
layout->addRow(button2, lineEdit2);
layout->addRow(button3, lineEdit3);

window->setLayout(layout);
window->show();

QFormLayout 将在一行上添加两个控件,通常是 QLabel 和 QLineEdit。在同一行中添加 QLabel 和 QLineEdit,将把 QLineEdit 设置为 QLabel 的伙伴。下面的代码将使用 QFormLayout 将三个 QPushButton 和相应 QLineEdit 排列起来。效果如下所示:

这里写图片描述

使用布局提示

当使用布局的时候,构建子控件的时候不需要指定 parent,布局将会自动的指定 parent(使用QWidget::setParent()),使它们成为安装了该布局的界面的子控件。

注意:布局中的控件是安装了该布局的界面的子控件,而非布局自身的,控件只能以控件作为parent,不能是布局。

也可以在布局中使用 addLayout() 来添加布局,内部的布局就会变成它的子布局。

为布局添加控件的过程分析

当添加一个控件到一个布局中,布局过程工作如下:

  • 所有的控件将最初根据它们的 QWidget::sizePolicy() 和 QWidget::sizeHint() 而被分配到一定空间中。

  • 如果任何一个控件有一个伸展因素设置,而且数值大于零,那么它们就会被根据它们的伸展因素的比例分配空间。

  • 如果任何一个控件有一个伸展因素设置而且数值为零,那么只有当其它控件不再需要空间的时候才会得到更多的空间。在这当中,空间会首先被根据延展大小策略分配给控件。

  • 任何控件被分配的空间的大小如果小于它们的最小大小(或者是在没有规定最小大小时的最小大小的提示),它们就会被按它们所需要的最小大小分配空间。(如果控件的伸展因素是它们的决定因素的情况下,它们不必有最小大小或者最小大小的提示。)

  • 任何控件被分配的空间的大小如果大于它们的最大大小,它们就会被按它们所需要的最大大小分配空间。(如果控件的伸展因素是它们的决定因素的情况下,它们不必有最大大小。)

伸展因素

控件通常是在没有伸展因素设置的情况下被生成的。当它们被布置到一个布局中时,控件会被根据它们的 QWidget::sizePolicy() 或者它们的最小大小的提示中大的那一个分配给整个空间的一部分。伸展因素是用来根据控件互相的比例来改变它们所被分配的空间。

如果你使用一个 QHBoxLayout 来布置没有伸展参数设置的三个控件,我们就会得到像下面这样的布局:

这里写图片描述

如果我们给每个控件设置一个伸展因素,它们就会被按比例布置(但是不能小于最小大小的提示),举例来说:

这里写图片描述

自定义控件的布局

当你创建自己的控件类时,也应该传递它的布局属性。如果这个控件有一个 QLayout,这样的话就已经被处理了。如果这个控件不包括任何子控件,或者使用自定义布局,需要重新实现下面这些 QWidget 的成员函数:

  • QWidget::sizeHint() 返回控件的优先选用的大小。
  • QWidget::minimumSizeHint() 返回控件所能有的最小大小。
  • QWidget::setSizePolicy() 指定控件所需要的空间。

只要大小提示、最小大小提示或者大小策略发生改变,都要调用 QWidget::updateGeometry()。这会引起布局的重新计算。对 updateGeometry() 的多重调用只会引起一次重新计算。

[扩展] Qt 布局学习资料

下面分析我在学习过程中看到的靠谱文章,学习Qt的布局,这几篇文章就足够入门了。

Qt编程指南 - 传统窗口调整技术

Qt编程指南 - 水平和垂直布局器

Qt编程指南 - 网格布局器

Qt编程指南 - 表单布局器

Qt编程指南 - 控件尺寸调整策略

Qt编程指南 - 分裂器

Qt 的官方文档:https://doc.qt.io/qt-5/layout.html.

参考:

Qt 之布局管理器

原文链接: https://www.cnblogs.com/linuxAndMcu/p/11600451.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

    Qt 布局之一:布局初探

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/303429

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月16日 上午12:15
下一篇 2023年2月16日 上午12:17

相关推荐