Qt 入门 6 之布局管理
Qt 入门 6 之布局管理
- 对于一个完整的软件,布局管理时必不可少的。其会让界面中嗯嗯部件呈现一个整齐的排列,也可令其大小随着窗口界面的大小变换而变化
- Qt 主要提供了
QLayout
类及其子类作为布局管理器,他们可以实现常用的布局管理功能,QLayout
类及其子类的关系如下图:
一. 布局管理系统
- 提供了强大的机制来自动排列窗口中的所有部件
- 所有
QWidget
的子类的实例(对象)都可以使用布局管理器管理位于它们之中的子部件,QWidget::setLayout()
函数可以在一个部件上应用布局管理器。 - 一旦一个部件上设置了布局管理器,那么它会完成以下几种任务:
- 定位子部件
- 感知窗口默认大小
- 感知窗口最小大小
- 窗口大小变化时进行处理
- 当内容改变时自动更新:
- 字体大小、文本或子部件的其他内容随之改变
- 隐藏或显示子部件
- 移除一个子部件
1.1 布局管理器
-
QLayout
类是布局管理器的基类,是一个抽象基类,继承自QObject
和QLayou-tItem
类,QLayoutltem类提供了一个供QLayout
操作的抽象项目。QLayout 和QLayoutltem
都是在设计自己的布局管理器时才使用的,一般只需要使用QLayout的几个子类即可,它们分别是QBoxLayout(基本布局管理器)、QGridlayout(栅格布局管理器)、QFormLayout(窗体布局管理器)和 QStackedlayout(栈布局管理器)
。 -
下面先来看一个例子。这打开Qt Creator,新建 Qt Widgets应用,项目名称为 mylayout,基类选择 QWidget,类名设为 MyWidget。
-
完成后打开
mywidget.ui
文件,在设计模式中向界面上拖入一个字体选择框Font Combo Box
和一个文本编辑器TextEdit
部件。然后单击主界面并按下Ctrl+L快捷键,或者单击设计器上部边栏中的曰图标来对主界面进行垂直布局管理也可以在主界面上右击,在弹出的级联菜单中选择“布局一垂直布局”。这样便设置了顶层布局管理器(因为是对整个窗口设置的布局管理器,所以叫顶层布局管理器),可以看到两个部件已经填满了整个界面。这时运行程序,然后拉伸窗口,两个部件会随着窗口的大小变化而变化,如下图所示。这就是布局管理器的作用
1.2 基本布局管理器(QBoxLayout)
-
基本布局管理器
QBoxLayout
类可以使子部件在水平方向或者垂直方向排成一列,它将所有的空间分成一行盒子,然后将每个部件放人一个盒子中。它有两个子类QHBoxLayout
水平布局管理器和QVBoxLayout
垂直布局管理器,编程中经常用到。再回到设计模式中看看布局管理器的属性。先单击主界面,查看它的属性栏,最后面的部分是其使用的布局管理器的属性,如下表所示:
-
下面打破已有的布局,使用代码实现水平布局,在界面上右击,然后在弹出的级联菜单中选择“打破布局”,或者单击设计器上方边栏中的打破布局图标。在
mywidget.cpp
文件添加头文件#include<QBoxLayout>
,并在MyWidget
类的构造函数中添加一下代码:
QHBoxLayout* layout =new QHBoxLayout; //新建水平布局管理器layout->addWidget(ui->fontComboBox); //向布局添加部件layout->addWidget(ui->textEdit);layout->setSpacing(40); //设置部件间的间隔layout->setContentsMargins(0,0,50,100); //设置布局管理器到边界的距离,左、上、右、下setLayout(layout);
- 运行结果如下:
1.3 栅格布局管理器(QGridLayout)
- 栅格布局管理器
QGridLayout
类使部件在网格中进行布局,它将所有的空间分隔成一些行和列,行和列的交叉处形成了单元格,然后将部件放入一个确定的单元格中先往界面上拖放一个Push Button
,然后在mywidget.cpp
中添加头文件#include<QGridlayout>
,再注释掉前面添加的关于水平布局管理器的代码,添加的如下:
//栅格布局QGridLayout* layout=new QGridLayout;//添加部件,从第0行0列开始,占据1行2列layout->addWidget(ui->fontComboBox,0,0,1,2);//添加部件,从第0行2列开始,占据1行1列layout->addWidget(ui->pushButton,0,2,1,1);//添加部件,从第1行0列开始,占据1行3列layout->addWidget(ui->textEdit,1,0,1,3);setLayout(layout);
- 这里主要是设置部件在栅格布局管理器中的位置,将
fontComboBox
部件设置为占据1行2列,而pushButton
部件占据1行1列,这主要是为了将fontComboBox
部件和pushButton
部件的长度设置为2:1。这样一来,textEdit部件要想占满剩下的空间就要使它的跨度为3列。这里需要说明,当部件加人到一个布局管理器中,然后将这个布局管理器再放到一个窗口部件上时,这个布局管理器以及它包含的所有部件都会自动重新定义自己的父对象(parent)为这个窗口部件,所以在创建布局管理器和其中的部件时并不用指定父部件。此外,也可以直接在设计模式时使用前面讲过的方法来使用栅格布局管理器
1.4 窗口布局管理器(QFormlayout)
- 窗体布局管理器
QFormLayout
类用来管理表单的输人部件以及与它们相关的标签。窗体布局管理器将它的子部件分为两列,左边是一些标签,右边是一些输入部件比如行编辑器或者数字选择框等。其实,如果只是起到这样的布局作用,那么用QGridLayout
就完全可以做到了,之所以添加QFormLayout
类,是因为它有独特的功能。下面看一个例子。 - 先将前面在
MyWidget
类的构造函数中自己添加的代码全部注释掉,然后进入设计模式,这里使用另外一种方法来使用布局管理器。从部件栏中找到FormLayout
,将其拖入到界面上,然后双击或者在它上面右击并在弹出级联菜单中选择“添加窗体布局行”。 在弹出的“添加表单布局行”对话框中填入标签文字“姓名(&N):”,这样下面便自动填写了“标签名称”、“字段类型”和“字段名称”等,并且设置了伙伴关系。这里使用了QLineEdit
行编辑器,当然也可以选择其他部件。填写的标签文字中的“(&.N)”必须是英语半角的括号,表明它的快捷键是At+N。设置伙伴关系表示按下At十N时,光标自动跳转到标签后面对应的行编辑器中。单击“确定”键,则会在布局管理器中添加一个标签和一个行编辑器。按照这种方法,再添加3行:性别(&S),使用QCo-moBox
;年龄(&A),使用QSpinBox
;邮箱(&M),使用QLineEdit
。
- 上面添加表单行是在设计器中完成的,其实也可以在代码中使用
addRow()
函数来完成。完成后运行程序,可以按下快捷键AIt+N,这样光标就可以定位到“姓名”标签后的行编辑器中。
1.5 综合使用布局管理器
- 前边讲到了3种布局管理器,真正使用时一般是将它们综合起来应用
1.综合应用
- 下边设置综合布局,先将
fontComboBox
和按钮pushButton
设置书评布局,然后在窗口布局管理器(QFormLayout)和水平布局中间添加一垂直分隔符(Vertical Spacer)用于设置部件之间的间隔,并在属性栏设置其高度100,最后右键整个ui文件选择设置整个界面布局为垂直布局,如下图: - 运行后结果和下图效果相似,并且支持缩放、但每个控件不是等比例的
2. 设置部件大小
- sizeHint 属性保存了部件的建议大小,而minimumSizeHint 保存了一个建议的最小大小提示。
- 可以在程序中使用
sizeHint()
函数来获取 sizeHint 的值,使用minimumSizeHint()
函数获取 minimumSizeHint 的值 - 如果使用了
setMinimumSize()
函数设置了部件的最小大小,那么最小大熊啊提示将会被忽略
- 可以在程序中使用
- 大小策略(sizePolicy)属性保存了部件的默认布局行为,在水平和垂直两个方向上分别起作用,控制着部件在布局管理器中的大小变化行为,sizePolicy 属性的所有取值如下表所示:
-
下面再来看一下窗体布局管理器中的一些属性,如下表:
-
下面看
QWidget
类及其子类部件的设置大小的相关属性:
- 最后看一下布局管理器的
layoutSizeConstraint
属性,它时用来约束窗口大小的:
3. 可扩展窗口
- 依然在前面的程序中进行更改。首先将界面上的
pushButton
显示文本更改为“显示可扩展窗口”,并在其属性栏选中checkable
选项。然后转到它的toggled(bool)信号的槽,更改如下:
void MyWidget::on_pushButton_toggled(bool checked)
{ui->textEdit->setVisible(checked); //设置文本编辑器的显示和隐藏if(checked)ui->pushButton->setText("隐藏可扩展窗口");elseui->pushButton->setText("显示可扩展窗口");
}
- 这里使用按钮的按下与否两种状态来设置文本编辑器是否显示,并且相应地更改按钮的文本。为了让文本编辑器在一开始是隐藏的,还要在
MyWidget
类的构造函数中添加一行代码:
ui->textEdit->hide();
- 运行程序结果如下:
4. 分裂器(QSplitter)
- 分裂器
QSplitter
类提供了一个分裂器部件。和QBoxLayout
类似,可以完成布局管理器的功能,但是包含在它里面的部件,默认是可以随着分裂器的大小变化而变化的。比如一个按钮放在布局管理器中,它的垂直方向默认是不会被拉伸的,但是放到分裂器中就可以被拉伸。还有一点不同就是,布局管理器继承自QObject
类,而分裂器却是继承自QFrame
类,QFrame
类又继承自QWidget
类,也就是说,分裂器拥有QWid-get类的特性,它是可见的,而且可以像QFrame
一样设置边框。 - 新建QtWidgets应用,项目名称为mysplitter,基类选择QWidget,类名设为MyWidget。建好项目后打开
mywid-get.ui
文件,然后往界面上拖人4个Push Button,同时选中这4个按钮,右击并在弹出的级联菜单中选择“布局一使用分裂器水平布局”,将这4个按钮放到一个分裂器中。将分裂器拉大点,并在属性栏中设置其frameShape为Box,frameShadow为Raised,lineWidth为5。此时运行程序,效果如下图所示:
二. 设置伙伴(buddy)
-
一个标签QLabel 经常用作一个交互式部件的说明,就像在将窗体布局管理器时看到的那样,一个lineEdit 部件前边有一个标签说明这个lineEdit 的作用
-
为了方便定位,QLabel提供了一个有用的机制,那就是提供了助记符来定位键盘焦点到对应的部件上,而这个部件就叫做这个QLabel的伙伴,其中助记符就是我们所说的加速键/快捷键。使用英文标签时,在字符串的一个字符前边添加“&”符号,就可以指定这个标签的快捷键是 Alt 加上这个字母;对于中文,需要小括号中指定快捷键字母
-
新建Qt QWidgets应用项目,命名为mybuddy,基类选QWidget。完成后打开
mywidget.ui
文件,往界面上拖放4个标签Label,再在标签后面依次放上PushButton、CheckBox、LineEdit 和 SpinBox
。然后将PushButton前面的标签文本改为“&.Button;”,CheckBox前面的标签文本改为“C&.heckBox:”,LineEdit前面的标签文本改为“行编辑器(&L):”,SpinBox前面的标签文本改为“数字选择框(&N):”。单击设计器上方边栏中的编辑伙伴图标民进入伙伴设计模式,分别将各个标签与它们后面的部件关联起来,如图4-8所示。然后按下F3键回到正常编辑模式,可以看到所有的&符号都不显示了。
-
编译运行程序,按下Alt+B快捷键,可以直接看到按钮被按下前后的状态变化、
三、设置 Tab 顺序
- 对于一个程序,有时总希望使用Tab 建将焦点从一个部件移动到下一个部件。在设计模式中,设计器提供了 Tab 键的设置功能
- 在前面程序的设计模式种,按下上方边栏的编辑Tab顺序按钮进入编辑Tab键顺序模式,这时已经显示了各个部件的Tab键顺序,只要单击这个数字就可以更改顺序。
- 设置好之后,可以运行一下程序测试效果。需要说明,当程序启动时,焦点会在Tab键顺序为1的部件上,这里进行的设置等价于在MyWidget 类的构造函数中使用如下代码:
setTabOrder(ui->lineEdit,ui->spinBox); //lineEdit在spinBox前面
setTabOrder(ui->spinBox,ui->pushButton); //spinBox在pushButton前面
setYabOrder(ui->pushButton,ui->checkBox); //pushButton在checkBox前面
四、Qt Creator中的定位器
-
定位器位于主界面的下方。使用定位器可以很方便的打开指定文件、定位到文档的指定行、打开一个特定的帮助文档、进行项目中函数的查找等
-
定位器中提供了多个过滤器来实现不同的功能,按下Ctrl+K快捷键就会在定位器中显示各个过滤器的前缀及其功能,如图所示。使用方法是“前缀符号十空格十要定位的内容”
-
下面举两个简单的例子。在QtCreator中,按下Ctrl+K快捷键打开定位器,这时输入
“l 8”
(英文字母l和一个空格,然后是数字8),按下Enter 回车键,就会跳转到编辑模式的当前打开文档的第8行。再次按下Ctrl十K
快捷键,输人“?qla”
,这时已经查找到了QLabel
,如下图所示,按下回车键,就会跳转到帮助模式中,并打开QLabel
类的帮助文档