了解布局,首先得清楚一个概念,就是容器控件。容器控件就是可以容纳别的控件的一种控件,如QWidget,所以就会出现父类控件与子类控件。为了很好的管理这种父子类控件,常用的有几种方法:
第一种就是使用绝对位置,setGeometry定位子类控件相对于父类控件。第二种就是常见的布局。
布局管理,其实就是为容器控件管理子类控件的位置和尺寸,所以布局本身没有存在的意义,其需要和容器控件搭配使用,为容器控件管理子控件服务。
而布局QLayout类其实只是一组预先撰写好的代码,相当于提前写出了以一个控件存放的规则,依据这种规则,进行对QWidget进行算法处理,在父控件尺寸变化时,根据预设参数和子控件的各种Geometry hint,管理控件的位置和尺寸。所以QLayout所管理的是哪个父类的QWidget的子控件,则最后将此layout通QWidget::setLaout设置。
布局被加载到一个容器窗口控件(容器控件)其将负责以下的工作任务:
1)放置窗口的子窗口
2)获取窗口部件的默认尺寸及最小尺寸
3)重新校正窗口尺寸处理
4)自动更新当内容改变时,比如字体大小,文本或者子窗口内容改变,或者显示或隐藏控件,删除子控件等情况。
使用布局管理控件,其加载目的是为了更好的调整各个控件所占用的空间,达到更好的显示效果。所以其需要对各个空间如何动态调整其尺寸策略。这就导致被管理控件的尺寸规则与布局放置控件占用的空间尺寸规则有些重图,那么需要一个规则去解决,当然首先需要确定如何将QWidget添加到QLayout,然后尺寸规则处理如下:
1)依据QWidget的sizePolicy()及QWidget::sizeHint()首先申请以一块空间
2)如果任何一个QWidget设置了拉升系数stretch factors,且其值大于0,则其按照此拉升系数申请一块空间。
3)如果widget的拉升系统被设置为0,如果其他控件不需要空间,则其可以获取更多的空间,。这样,QWidget可以扩充控件依据尺寸策略
4)如果控件申请的空间比这个QWidget控件的minimum尺寸(或者hint计算出来的大小)还小则申请这个空间尺寸为minimum
5)任何一个控件申请的空间大于控件最大尺寸maxmum,则设定为控件最大值maxmun作为尺寸
拉升系数(因子)stretch factors是用来改变各个各个控件的空间尺寸比例。默认widgets是创建一个没有拉升系统的控件
注:因为QWidget类本身并不是一个QLayoutItem,而Qlayout的管理又是以QLayoutItem为单位。所以,在addWidget的操作中,QLayout还会创建一个QLayoutItem的子类QWidgetItem类来对应的包装代理添加进来的子控件。QWidgetItem对象最终会将QLayout布局管理体系中的布局参数信息装换、设置到它所代理的QWidget对象上。
Qt提供了常见的以QLayout为基类的布局类,即QBoxLayout,QGridLayout,QFormLayout及QStackedLayout。
1、QLayout:是所有布局类的基类,是个抽象类,用户可以根据自己的布局规则实现布局类。因为布局类就好比一个管理控件的框架,对所要填制控件的位置都进行了规定和标记,制定好规矩,然后根据此规矩和要求添加相对应的控件。比如QBoxLayout需要制定顺序,是左右,上下的等等
如果需要实现自己的布局模板,需要实现addItem函数,sizeHint()函数,setGeometry(),ienmA函数及takeAt和tItemAt等函数,此些函数都是根据规则确定控件存放的空间的pos位置信息并以此计算尺寸的信息。当然可以实现minimumSize()以保证当空间非常小的时候layout不会重设定大小为0。为了支持子子类其高度决定其宽度,需要实现hasHeightForWidth和heightForWidth函数。
最重要的枚举定义enum QLayout::SizeConstraint尺寸策略,其会对安装了此layout的主容器窗口进行大小的调整,以保证恰到好处,因为layout基本保持与主窗口空间填充满。
1)QLayout::seetDefaultConstraint 0:主窗口最小值被设置为minimumSize(),即layout管理所需的最小空间尺寸,除非空间widget已经有最小的minimumSize尺寸。
2)QLayout::SetFixedSize 3,主窗口的大小被设定为sizeHint()刚好适配好的大小,并不能再被重新设定大小。
3)QLayout::SetMinimumSize 2,设定主窗口minimumSize为minimumSize()定义的,其不能再小
4)QLayout::SetMaxmumSize 4,设定主窗口的最大尺寸maxmumSize到maxmumSize()函数确定的尺寸,其不能大于这个尺寸。
5)QLayout::SetMinAndMaxSize 5,设定主窗口的大小尺寸分别为minimumSize和maxmunSize
6)QLayout::setNoConstraint 1,主窗口不设定尺寸策略,保持用户设定的已有属性
1.1 Layout属性
1)sizeConstraint : SizeConstraint 此属性保存布局重置大小的方式
SizeConstraint sizeConstraint()访问其值,setSizeConstraint(SizeConstraint)设置
2)spacing:int 保存在布局里面两个widget空间之间的间隔。如果没有设置则其继承父layout布局的大小,或者设置父窗口的样式属性内。
在QGridLayout和QFormLayout,可以使用setHorizontalSpacing()和setVerticalSpacing(),这样的话spacing则返回-1。使用spacing进行获取,setSpaicing(int val)进行设置
1.2 QLayout常见接口
1)addItem(QLayoutItem *item)纯虚函数,其实现子类必须实现。所以如何添加依赖于具体的实现法则。通常加一个窗口不见widget到布局layout时使用addWidget接口,添加一个子布局使用addLayout接口。此接口不常用,其使用原理是将addWidget的widget和addLayout的layout会添加到此变量上去。
2)addWidget(QWidget *w)将这个窗口部件添加到指定的布局上,其使用addItem
3)QSize closestAcceptableSize ( const QWidget * widget, const QSize &size ) [static]
返回满足所有限制策略的大小尺寸给widget,包括heightForWidth(),并且尽可能接近size大小。
4)QMargins contentsMargins()返回布局周边的边距。绝大多数边距使用11像素到各个方向
void QLayout::setContentsMargins ( int left, int top, int right, int bottom )
void QLayout::setContentsMargins ( const QMargins & margins )
设置不同方向的边距。
5)QRect QLayout::contentsRect ()返回布局的矩形大小,但需要考虑内容边界。
6)int count()纯虚函数,实现布局实习那,表示此布局的item数量
7)Qt::Orientations QLayout::expandingDirections () const [virtual]
返回layout扩展的方向,一般是Qt::Vertical或者Qt::Horizontal表示只想一个方向grow,否则是两个方向。
8)QRect QLayout::geometry () const [virtual]
返回此布局占用的几何空间,矩形显示,其余contentRect不同setGeometry设置尺寸
9)int QLayout::indexOf ( QWidget * widget ) const [virtual]
返回布局空间的索引序号,同count使用一样,layout使用index为了便于管理其应的控件。-1表示没有找到。默认的实现方法是使用itemAt查询,但其不会搜索子布局。.
10)bool QLayout::isEmpty () const [virtual]判断布局下空间是否为空
11)isEnable()如果为true,layout是激活的enabled,使用setEnabled进行设置。
12)QLayoutItem * QLayout::itemAt ( int index ) const [pure virtual]
纯虚函数,需要具体子类进行实现,如果index位置没有控件,则返回0。items是进行编号的,如果某个控件删除了,则重新编号
13)layout()如果其控件是个布局,则返回布局,否则返回0
14)QSize QLayout::maximumSize () const [virtual]返回布局的最大值,是布局扩展的最大值
15) QSize QLayout::minimumSize () const [virtual]返回模具的最小值,是布局可被压缩最小值
16)QWidget parentWidget():返回主窗口控件的布局,如果这个布局没有安装到任何窗口上,则返回0。如果此布局是一个子布局,则其返回父类布局的父类窗口部件。
17)void removeItem(QLayoutItem *item)删除一个布局的控件。释放delete 这个选项是用户调的责任
18)void remobeWidget(QWidget *w)从一个布局删除一个控件。这是调用者则取去保证widget一个可给出可用的控件或者又放回布局
19)bool setAlignment(QWidget * w,Qt::Alignment alignment)设置窗口部件w对齐模式,如果w在布局中找到(不包含子类布局)窗口w,则返回true,否则返回false
20)void setAlignment(Qt::Alignmen alignment)设置当前布局的对其模式。
bool setAlignment(QLayout *k,Qt::Alignment)设置一个对其方式给布局了,如果被拒找到了,不再子布局中找,则返回true,否则返回false。
21)void setMenuBar(QWidget *w)告诉尺寸管理者将菜单条放置到界面到parentWidget父窗口的最上层。其最所有的控件都防止到按钮边缘下面。
22)voud update()更新父控件的布局。
23)QLayoutItem takeAt(int index) 纯虚函数,子类实现必须实现的函数,此目的是删除布局index所指的选项,并返回该选项。如果没有选项,则其什么都不做并且返回0.
总之,QLayout作为所有实现类的基类,其包含sizeConstraint属性及spacing属性保证布局控件如何限制约束及布局内项目之间的距离。布局是可以嵌套的,通过setAlignment设置函数设置子类widget对其方式,以及设置获取布局的几何尺寸geometry,设置获取内容的边距contengsMargin。布局需要添加和删除控件,一起通过index查找指定的控件并作操作等。