做为一名 iOS 开发人员, 见证着 iOS 布局系统的不断完善, 从绝对布局, Autoresizing 到 Autolayout. 使得开发人员的工做效率愈来愈高, 项目界面的可读性和易维护性愈来愈强. 现在 IDE 中的可视化界面工具已经很是强大, 许多网友"戏称" iOS 开发者为"UI 拖拽师", 可见, iOS 开发中界面布局系统的高效. 因此, 优秀的布局系统的使命在于让开发者花更少的时间来完成更易维护的界面.浏览器
一样的, 在 Qt 中, 系统提供了强大的排版机制来为窗口中的视图进行布局排版, 通过了对 Qt 布局一个初步的探索, 不得不对 Qt 布局系统的简洁高效而又功能强大表示赞叹.函数
在 Qt 中, 布局系统能够完成工具
Qt 提供了 QLayout 类及其子类来为界面进行排版布局. 结构以下图:布局
QLayout 是布局系统中的抽象基类, 继承自 QObject 和 QLayoutItem, 其中四个子类分别为学习
在真实使用场景中, 每每须要经过多种布局的相结合来完成界面的设计, 接下来将分别介绍四中布局.字体
箱式布局提供了两个子类分别处理水平(QHBoxLayout)和垂直(QVBoxLayout)两个方向的排版, 可使视图排成一行或者一列来显示. 简单说, 就是可让控件进行排排站, 好比在咱们的 AlphaBox 中, 顶部的头像, 姓名, 和刷新按钮排成了一排, 这就是水平箱式布局:spa
你觉得我要讲一下这个东西如何实现? NO, 我恰恰要以垂直箱式布局为例, 用一个最简单的例子来介绍箱式布局的使用, 首先建立一个基于 QWidget 的界面, 添加咱们须要使用的头文件:翻译
#include <QVBoxLayout>
#include <QPushButton>
复制代码
并在构造函数中添加以下代码设计
// 添加两个按钮
QPushButton *okBtn = new QPushButton;
okBtn ->setText(tr("我在上面, 我最牛"));
QPushButton *celBtn = new QPushButton;
celBtn->setText(tr("我在下面, 我不服"));
// 建立一个垂直箱式布局, 将两个按钮扔进去
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(okBtn);
layout->addWidget(celBtn);
// 设置界面的布局为垂直箱式布局
setLayout(layout);
复制代码
运行看一下效果, 什么? 这就能够运行了? 坐标呢? 尺寸呢? 是的, 没看错...点击运行:3d
两个按钮已经一上一下, 乖乖的在垂直方向本身站好了位置, 就是这么强大, 就是这么省心.
强大的 AlphaBox 是很外向的, 能够很轻松的将你的资料分享给其余用户, 当咱们分享的时候, 会有这样一个界面:
看到这个界面, 聪明的你可能会说, 这很简单啊, 好几个水平箱式布局就能够实现, 但是, 更聪明的 Qt 提供了更高效的方式帮助你完成这样一个界面, 那就是 QFormLayout.
在我所学习 Qt 所使用的书籍中, 将 QFormLayout 翻译为窗体布局, 我我的认为, 将其翻译为表单布局更为贴切, 由于 QFormLayout 的强大之处正是可使用最快的速度完成一个用户输入的表单界面的搭建.
那么, 让咱们揭开 AlphaBox 的神秘面纱, 看看这样一个界面是怎么实现的.
首先, 拖拽一个 Form Layout 到 Widget 中.
双击以后便可为表单增长一行.
相信你们看到这张图时, 就已经能理解到表单布局是如何使用的, 提供了标签做为用户输入内容的指引, 提供字段类型做为用户输入的控件, 做为 iOS 开发者, 深知这样一个界面的搭建所须要的繁杂的工做量. 当我第一次打开这个界面时, 被这样建立界面的方式所惊呆了.
快不快? 快不快! 快不快!!!
一样的, 若是是使用纯代码表单布局的话可使用addRow()
的方法来添加一行.
事实上, 强大的 AlphaBox 是这样的, 咱们能够共享给多个用户, 并且, 下方会有一个列表, 展现共享的用户以及权限列表. 这时, 表单布局就没办法知足咱们, 只好另求新欢 QGridLayout - 网格布局.
网格布局顾名思义, 能够将界面分割成行列来进行布局管理, 在每一个单元格中来摆放控件. 因此 AlphaBox 分享的界面使用了一个 两行三列 的网格布局来实现的.
固然, 更更复杂的界面, 用 Qt 布局的效率也是很是高的, 我作了一个外链分享的布局 Demo, 能够将内部资料生成一个下载连接共享给任何人去下载.
这个界面中, 我在Tab以内使用了网格布局, 布局如图:
从图中能够看出, 网格布局像是在操做一个 Excel 同样简单, 布局单元格, 合并单元格, 等等.
在这个界面中, 更灵活的使用了 QLayout 的属性来完成了界面布局排版.
一样的, 在代码中, 可使用以下等的 Api 来为网格视图添加一个从几行几列开始占据几行几列的控件:
void addWidget(QWidget *, int row, int column, int rowSpan, int columnSpan) 复制代码
如在 AlphaBox 中, 咱们能够经过云端文件浏览器直接查看和操做云端文件, 在加载的过程当中, 会有一个转菊花的界面.
加载失败时的错误提示:
以及加载成功时:
一般应用的界面会根据不一样的状态有不一样的内容, 这时就可使用 QStackedLayout 栈布局, 栈布局提供了一个页面的栈, 每一个页面有彻底独立的界面布局. 能够很是清晰的对不一样状态下的界面进行布局管理.
在 Qt 的可视化布局工具中, 经过 Stacked Widget 来完成界面的栈布局
经过右键来进行页面的插入移除和排序等操做.
对于控件大小, 最重要的两个属性是 sizeHint
和 minimumSizeHint
, 这是 QWidget 的属性, 是只读属性. 其中, sizeHint
属性为控件的建议大小, 对于不一样的控件, 有不一样的建议大小, 同理 minimumSizeHint
为建议的最小大小. 知道了这两个属性才能够理解布局中控件的大小是如何控制的. 若是手动设置了最小尺寸的话(minimumSize
), minimumSizeHint
是会被忽略的.
大小策略属性 sizePolicy
也是 QWidget 类的属性, 这个属性在水平和垂直两个方向分别起做用, 控制着控件大小变化的策略.
在可视化工具中能够直观的看到几种大小策略, 以垂直为例如图:
QSizePolicy::Fixed
只能使用 sizeHint 的大小, 任何操做都不会改变控件大小QSizePolicy::Minimum
sizeHint 为最小大小, 控件能够被拉伸QSizePolicy::Maximum
sizeHint 为最大大小, 控件能够被压缩QSizePolicy::Preferred
sizeHint 为建议大小, 控件既能够被压缩也能够被拉伸QSizePolicy::MinimumExpanding
sizeHint 为最小大小, 不能被压缩, 被拉伸的优先级更高QSizePolicy::Expanding
sizeHint 为建议大小, 能够被压缩, 被拉伸的优先级更高QSizePolicy::Ignored
sizeHint 的值将会被忽略在网上或者书中, 关于这些策略的说明会有不少, 但是若是不是真的本身尝试一下, 很难很好的理解在复杂布局的状况下, 大小策略是如何控制布局的, 尤为是 MinimumExpanding
, Expanding
, Ignored
这三种.
对于优先级的概念你们确定不会陌生, 这里我认为优先级来解释这些策略是更清晰易懂的.
关于拉伸 Expanding
, MinimumExpanding
优先级相同, 同时要比 Preferred
和 Ignored
拉伸优先级更高, Preferred
和 Ignored
相同.
换句话说, 若是两个控件在一个水平箱式布局中管理, 其中一个水平大小策略为 Preferred
另外一个为 Expanding
或者 MinimumExpanding
若是水平拉伸窗体, 则 Preferred
的控件大小不会改变, Expanding
或者是 MinimumExpanding
会被拉伸.
同理, 若是两个控件水平大小策略一个为Expanding
, 一个是MinimumExpanding
, 这时拉伸窗体, 则两个控件均会拉伸.
多说一句, 若是两个控件都为 Fixed
没法拉伸时, 控件间的间隙会被拉伸.
关于压缩 若是达到了minimumSizeHint
是不会被继续压缩了, 可是Ignored
是会忽略 sizeHint
和 minimumSizeHint
的属性的, 因此是会继续被压缩的.
在 QLayout 中提供了一个和控件大小策略相关的属性, layoutStretch
布局伸缩性, 这个值是一个比例, 在可视化工具中能够更直观的看到这个值的设置, 若是在布局中有三个控件, 则是三个控件的占比, 用逗号分隔, 如: 1, 1, 1
.
伸缩性就好理解一些了, 可是要注意的是, 只有会被压缩或者拉伸的控件才会受该属性值影响(如 Fixed
是不会受该属性影响)
还有一点很是重要的是设置了伸缩性的比值(若是都为0, 则表示不设置) 刚刚提到的大小策略的优先级将会被忽略, 仍是刚刚的例子, 若是两个控件在一个水平箱式布局中管理, 其中一个水平大小策略为 Preferred
另外一个为 Expanding
, 设置水平箱式布局的 layoutStretch
为 2, 1
则拉伸时, 并不会像刚刚所说, 只有 Expanding
的控件会被拉伸, 而是都会被拉伸, 按照一个 2 : 1 的拉伸比例拉伸.
最后想介绍一下 QLayout 的 layoutSizeConstraint
属性, 用来约束窗体大小, 只影响窗体, 因此该属性只对最顶级的 QLayout 起做用.
关于这几个属性一样的, 简单的介绍网上和书上会有不少, 若是不尝试一下, 浅显的字面意思没法理解这几个属性的做用. 根据个人尝试, 总结以下:
QLayout::SetDefaultConstraint
窗体最小值被设置为 minimumSize 值没法再缩小, 若是 QLayout 内控件有更大的minimumSize, 则会取更大的minimumSize.QLayout::SetNoConstraint
窗体没有约束策略QLayout::SetFixedSize
,窗体大小被设定为 sizeHint 的大小,没法改变QLayout::SetMinimumSize
窗体最小为 minimumSize 没法再缩小, 若是 QLayout 内控件有更小的minimumSize, 则会取更小的minimumSize., 总结就是的话, 和 Default 不一样的地方就是尽量的小.QLayout::SetMaxmumSize
同理, 窗体最大值为 maxmumSize , 没法再放大QLayout::SetMinAndMaxSize
窗体最小为 minimumSize 没法再缩小, 窗体最大值为 maxmumSize , 没法再放大关于表单布局和网格布局还有其余的属性约束单元格的一些策略, 如 layoutFieldGrowthPolicy
控件的变化方式策略等等有兴趣能够查看官方文档, 更多的属性间隙, 间隔, 对其方式等等都比较好理解了, 在此也不赘述了.
<< Qt Creator 快速入门>> 第三版, 霍亚飞著