最近老师让搞的东西,想用QT做界面,但是计划好的布局到真正运行总是出现一些坑爹的效果,网上找了好多布局的资料都是点到即止,后来终于找到了比较好懂而且全面的下面这篇博文,作者写得很详细,没有故弄玄虚,看了以后对QT的布局有了比较全面的了解,也跟SWING 和SWT比较了下,感觉QT从总体设计上都是C++的思路,看起来自己对于JAVA和C++的理解还是不够深入。
1、QFormLayout:表单布局,顾名思义就是实现表单模式的布局。表单就是提示用户进行交互的一种模式,其主要有两个列组成,第一个列用于显示信息,给予用提提示,一般叫做label域,第二个是需要用户选择输入的,一般叫field域。表单就是很多由这两项/两列内容组成的行的布局。label与field关系就是label是关联field的。
表单布局完全可以使用表格布局实现,是一种多行两列的列表,但表单布局提供一种比较完善的策略,其主要有以下优点
1)可以适应不同平台外观和感觉的一致性
2)支持一行的label和field域换行显示,有两种策略一种是如果输入域过长,field换行显示,还有一种就是不管怎么样都换行显示,当然默认是一行显示两个域就可以了
3)创造label--field对很便捷的接口,因为使用一般的布局,想要关联label和field,创建好label和feild,并且调用label的setBuddy才能完成,但formlayout使用addRow就可以直接对应了。
表单布局的样式可以通过几个方面体现
1)label的样式,是左对齐还是右对齐,可以使用setLabelAlignment进行设置
2)form的样式,其内容的显示方式,则可以通过setFormAlignment进行设置
3)表单一行内容的显示,是否换行,则使用setRowWrapPolicy设置,主要值是DontWrap
Rows,即Field域永远跟着其label;WrapLongRows,给予label足够的空间,剩余的空间给field域,如果field域的最小空间比剩余的控件大/宽,则field会换行到下一行显示;WrapAllRows,所有的field域不管后面剩余的空间是否够,都自动换行。
4)filed域拉升生长策略growth policy,其主要是FieldGrowthPolicy控制,首先是FieldStayAtSizeHint 0 ,field域永远不会超过有效的sizehint尺寸;ExpandingFieldGrow 1,field域水平尺寸拉升或者最小值超出时会占用可用空间,其他field在sizehint尺寸下不会扩大grow;AllNonFixedFieldGrow 2所有的field允许他们长grow就长grow到填充可用的空间,如果是fixed固定尺寸策略的field则不会长
表单由两列组成,所以一本都是分为label和field域,但是有些控件占用两行,所以对每个行其可以通过角色来访问,如LabelRole 0,一个label控件,FieldRole 1,一个field空间,SpanningRole就是占用了label和field两列的控件。当访问某一个行的某个特定的空间时,如果不知道具体名,则可以通过此角色访问。
1.1 表单布局formLayout的属性
1)fieldGrowthPolicy :FieldGrowthPolicy ,表示feild域如何扩张延伸的方式
如果没有任何一个field域可以延伸并且表单form重置了大小,多余的空间会根据当前的表单form aligment对齐方式分部。
fieldGrowthPolicy()获取此属性。setFieldGrowthPolicy(FieldGrowthPolicy)进行设置
2)formAligment : Qt::Alignment ,此属性表示扁担布局formlayout内容的对齐方式。使用formAlignment()获取,setFormAlignment(Qt::Alignment)进行设置
3)horizontalSpacing :int表示每行空间之间的空间间隔。通过horizontalSpacing()获取,setHorizontalSpacing(int)设置
4)域horizontalSpacing对应的是verticalSpacing保存了垂直放置的控件之间的间隔。verticalSpacing获取,setVerticalSpacing设置。
5)labelAlignment:Qt::Alignment 保存标签label水平方向的对齐alignment模式。
通过labelAlignment()获取,setLabelAlignment进行设置。
6)rowWrapPolicy : RowWrapPolicy保存表行每行换行的方式。其可见值概述已做详细描述
1.2 QFormLayout的接口
表单布局是以行作为基本单位的,所以需要为表单布局添加控件,一个是标签域label,一个是输入域field,通过addRow方法进行添加。
1)添加一行表单
添加第一个域可以是QWidget或者QString,如果是后者会自动创建一个QLabel,并且将field的QWidget设置为label的buddy。field可以是QLayout或者QWidget。
如果是占用两行的空间,则只有一个变量,可以是QWidget或者QLayout。具体形式如下
void addRow(QWidget *label,QWidget *field):添加一行到布局末尾,使用label和field填充表单布局的对应域。
void addRow(QWidget *label,QLayout *layout):
void addRow(const QString *labelText,QWidget *widget):会把widget设置为qlabel的buddy
void addRow(const QString *labelText,QLayout *layout):
void addRow(QWidget *widget):占用两列
void addRow(QLayout *layout):占用两列
int count(),返回有多少个元素,在后续查找、插入和删除的时候用。
2)查找元素
void getItemPosition(int index,int *rowPtr,ItemRole *rolePtr):找到指定位置index元素item的行数row值和角色值。如果index越界了,rowptr值被设置为-1,让否则将值存到rowPtr和rolePtr中。
void getLayoutPosition(QLayout *layout,int *rowPtr,ItemRole *rolePtr)
找到特定的子布局layout的行号row和role(colume)。如果layout不在formLayout,那么rowPtr设置为-1,否则正确设置。
void getWidgetPosition(QWidget *w,int *rowPtr,ItemRole *rolePtr)追溯控件w在布局中的行号row和角色role。如果此布局没有w,则rowPtr返回 -1.
QLayoutItem *itemAt(int index)返回索引为index的控件
QLayoutItem *itemAt(int row,ItemRole role)返回布局中元素在row行角色是role的控件,如果没有则返回0
QLayoutItem * QFormLayout::takeAt ( int index )获取索引为index的元素并删除原来的元素
3)插入元素,与addRow对应,只是添加一个参数及int row,指定在某个行之后添加。如果row越界,则自动添加到最后一行。
setItem(int row,ItemRole role,QLayoutItem *item)将item元素设置到指定的行号row的指定角色role的位置。如果此处的位置已经被占用了,则插入失败。
void setLayout(int row,ItemRole role,QLayout *layout)将指定的layout设置到行row角色为role的位置,根据需要扩展没有行元素的布局。如果此单元被占用,则不会插入
void setWidget(int row,ItemRole,QWidget *widget)将指定的widget设置到行row角色为role的位置,根据需要扩展没有行元素的布局。如果此单元被占用,则不会插入
4)QWidget *labelForField(QWidget *field)返回与field关联的label控件
QWidget *labelForLayout(QLayout *layout)返回与field关联的label控件
5)QSize minimumSize()获取布局的最小尺寸,对应的有maxmumSize最大尺寸
6)rowCount()返回此布局中有多少行
7)setGeometry(QRect rect)设置布局的空间大小
8)void setSpacing(int spacing)设置垂直和水平方向的空间间隔。spacing()返回这个值,前提是horizontal和vertical空间相等
具体使用见一个简单的输入例子:用户登录信息窗口
#include
#include
#include
#include
voidinitLayout(