【QT编程】QT布局管理

01、目录

目录

      • 01、目录
      • 02、布局管理系统
      • 03、布局管理器
        • 3.1、基本布局管理器(QBoxLayout)
        • 3.2、棚格布局管理器(QGridLayout)
        • 3.3、窗体布局管理器(QFormLayout)
        • 3.4、综合使用布局管理器
      • 04、设置部件大小
      • 05、可扩展窗口
      • 06、分裂器(QSplitter)
      • 07、设置伙伴(buddy)
      • 08、Tab键顺序
      • 09、布局管理小结

02、布局管理系统

Qt的布局管理系统提供了强大的机制来自动排列窗口中的所有部件,确保它们有效地使用空间。Qt包含了一组布局管理类,从而在应用程序的用户界面中对部件进行布局,比如 QLayout的几个子类,这里将它们称作布局管理器。所有QWidget的子类的实例(对象)都可以使用布局管理器管理位于它们之中的子部件,QWidget::setLayout()函数可以在一个部件上应用布局管理器。一旦一个部件上设置了布局管理器,那么它会完成以下几种任务:

  1. 定位子部件;
  2. 感知窗口默认大小;
  3. 感知窗口最小大小;
  4. 窗口大小变化时进行处理:
  5. 当内容改变时自动更新;
    字体大小、文本或子部件的其他内容随之改变;
    隐藏或显示子部件;
    移除一个子部件。

03、布局管理器

QLayout类是布局管理器的基类,是一个抽象基类,继承自QObjectQLayoutItem类,QLayoutItem类提供了一个供QLayout 操作的抽象项目。QLayoutQLayoutItem都是在设计自己的布局管理器时才使用的,一般只需要使用QLayout的几个子类即可,它们分别是QBoxLayout(基本布局管理器).QGridLayout(栅格布局管理器),QFormLayout(窗体布局管理器)和QStackedLayout(栈布局管理器)。

下面先来看一个例子:

  • 打开QtCreator,新建Qt Widgets应用,项目名称为mylayout,基类选择QWidget,类名设为MyWidget。
  • 完成后打开 mywidget. ui文件,在设计模式中向界面上拖入一个字体选择框Font Combo Box和一个文本编辑器Text Edit部件。然后单击主界面并按下Ctrl+L快捷键,或者单击设计器上部边栏中的垂直布局来对主界面进行垂直布局管理。也可以在主界面上右击,在弹出的级联菜单中选择“布局→垂直布局”。

这样便设置了顶层布局管理器(因为是对整个窗口设置的布局管理器,所以叫顶层布局管理器),可以看到两个部件已经填满了整个界面。这时运行程序,然后拉伸窗口,两个部件会随着窗口的大小变化而变化,如下图所示。这就是布局管理器的作用。

【QT编程】QT布局管理_第1张图片

3.1、基本布局管理器(QBoxLayout)

基本布局管理器QBoxLayout类可以使子部件在水平方向或者垂直方向排成一列,它将所有的空间分成一行盒子,然后将每个部件放入一个盒子中。它有两个子类QHBoxLayout水平布局管理器和QVBoxLayout垂直布局管理器,编程中经常用到。再回到设计模式中看看布局管理器的属性。先单击主界面,查看它的属性栏,最后面的部分是其使用的布局管理器的属性,如下表所列。

属性 说明
LayoutName 现在所使用的的布局管理器名称
layoutLeftMargin 设置布局管理器到界面左边界的距离
layoutTopMargin 设置布局管理器到界面土边界的距离
layoutRightMargin 设置布局管理器到界面右边界的距离
layoutBottomMargin 设置布局管理器到界面下边界的距离
layoutSpacing 布局管理器中各个子部件间的距离
layoutStretch 伸缩因子
layoutSizeConstraint 设置大小约束条件

下面打破已有的布局,使用代码实现水平布局。在界面上右击,然后在弹出的级联菜单中选择“打破布局”,或者单击设计器上方边栏中的打破布局图标。在mywidget.cpp文件中添加头文件#include,并在 MyWidget类的构造函数中添加如下代码:

QHBoxLayout* layou = new QHBoxLayou;  //新建水平布局管理器
layout->addWidget(ui->fontComboBox);  //向布局管理器中添加部件
layout->addWidget(ui->textEdit);      
layout->setSpacing(50);              //设置部件间的间隔
layout->setContentsMargins(0,0,50,100);  //设置布局管理器到边界的距离,参数:左、上、右、下
setLayout(layout);                  //将这个布局设置为MyWidget类的布局

这里使用了addWidget()函数向布局管理器的末尾添加部件,还有一个insertWidget()函数可以实现向指定位置添加部件,它比前者更灵活。前者使用的垂直布局管理器也可以通过相似的代码来实现。

3.2、棚格布局管理器(QGridLayout)

栅格布局管理器QGridLayout类使部件在网格中进行布局,它将所有的空间分隔成一些行和列,行和列的交叉处形成了单元格,然后将部件放人一个确定的单元格中。先往界面上拖放一个Push Button,然后在mywidget. cpp中添加头文件#include

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)为这个窗口部件,所以在创建布局管理器和其中的部件时并不用指定父部件。此外,也可以直接在设计模式时使用前面讲过的方法来使用栅格布局管理器。

3.3、窗体布局管理器(QFormLayout)

窗体布局管理器QFormLayout类用来管理表单的输人部件以及与它们相关的标签。窗体布局管理器将它的子部件分为两列,左边是一些标签,右边是一些输入部件,比如行编辑器或者数字选择框等。其实,如果只是起到这样的布局作用,那么用QGridLayout就完全可以做到了,之所以添加QFormLayout类,是因为它有独特的功能。下面看一个例子。

先将前面在 MyWidget类的构造函数中自己添加的代码全部注释掉,然后进入设计模式,这里使用另外一种方法来使用布局管理器。从部件栏中找到Form Layout,将其拖入到界面上,然后双击或者在它上面右击并在弹出级联菜单中选择“添加窗体布局行”。在弹出的“添加表单布局行”对话框中填入标签文字“姓名(&.N):”,这样下面便自动填写了“标签名称”、“字段类型”和“字段名称”等,并且设置了伙伴关系。这里使用了QLineEdit行编辑器,当然也可以选择其他部件。填写的标签文字中的“(&.N)”必须是英语半角的括号,表明它的快捷键是Alt+N。设置伙伴关系表示按下Alt+N时,光标自动跳转到标签后面对应的行编辑器中。单击“确定”键,则会在布局管理器中添加一个标签和一个行编辑器。按照这种方法,再添加3行:性别(&S),使用QCo-moBox;年龄(&-A),使用QSpinBox;邮箱(&.M),使用QLineEdit。完成后运行程序,可以按下快捷键Alt十N,这样光标就可以定位到“姓名”标签后的行编辑器中。
上面添加表单行是在设计器中完成的,其实也可以在代码中使用addRow()函数来完成。窗体布局管理器为设计表单窗口提供了多方面的支持,其实它还有一些实用的特性,这个以后再说。窗体管理器也可以像普通管理器一样使用,但是,如果不是为了设计这样的表单,一般会使用棚格布局管理器。

3.4、综合使用布局管理器

前面说到了3种布局管理器,真正使用时一般是将它们综合起来应用。

现在将前面的界面再进行设计;按下Ctrl键的同时选中界面上的字体选择框fontComboBox和按钮 pushButton,然后按下Ctrl+H快捷键将它们放入一个水平布局管理器中(其实也可以从部件栏中拖人一个 Horizontal Layout,然后再将这两个部件放进去,效果是一样的)。然后再从部件栏中拖入一个Vertical Spacer垂直分隔符,用来在部件间产生间隔,将它放在窗体布局管理器与水平布局管理器之间。最后单击主界面并按下Ctrl+L快捷键,让整个界面处于一个垂直布局管理器中。这时可以在右上角的对象列表中选择分隔符Spacer,然后在属性栏中设置它的高度为100,如下图所示。这时运行程序可以看到,分隔符是不显示的。
【QT编程】QT布局管理_第2张图片

这里综合使用了窗体布局管理器、水平布局管理器和垂直布局管理器,其中,垂直布局管理器是顶级布局管理器,因为它是主界面的布局,其他两个布局管理器都包含在它里面。如果要使用代码来实现将一个子布局管理器放入一个父布局管理器之中,则可以使用父布局管理器的addLayout()函数。

04、设置部件大小

学习之前要先了解两个概念:大小提示( sizeHint)和最小大小提示( minimumSize-Hint)。凡是继承自QWidget 的类都有这两个属性,其中,sizeHint属性保存了部件的建议大小,对于不同的部件,默认拥有不同的sizeHint;而 minimumSizeHint保存了一个建议的最小大小提示。可以在程序中使用sizeHint()函数来获取sizeHint的值,使用minimumSizeHint()函数获取minimumSizeHint的值。需要说明的是,如果使用setMinimumSize()函数设置了部件的最小大小,那么最小大小提示将会被忽略。这两个属性在使用布局时起到了很重要的作用。

下面再来看一下大小策略( sizePolicy)属性,它也是QWidget类的属性。这个属性保存了部件的默认布局行为,在水平和垂直两个方向分别起作用,控制着部件在布局管理器中的大小变化行为。sizePolicy属性的所有取值如下表所示:

常量 描述
QSizePolicy::Fixed 只能使用sizeHint()提供的值,无法伸缩
QSizePolicy::Minimum sizeHint()提供的大小是最小的,部件可以被拉伸
QSizePolicy::Maximum sizeHint()提供的是最大大小,部件可以被压缩
QSizePolicy::Preferred sizeHint()提供的大小是最佳大小,部件可以被压缩或拉伸
QSizePolicy::Expanding sizeHint()提供的是最合适的大小,部件可以被压缩,不过它更倾向于被拉伸来获得更多的空间
QSizePolicy::MinimumExpanding sizeHint()提供的大小是最小的,部件倾向于被拉伸来获取更多的空间
QSizePolicy::Lgnored sizeHint()的值被忽略,部件将尽可能的被拉伸来获取更多的空间

可以看到,大小策略与sizeHint()的值息息相关。对于布局管理器来说,大小策略对于布局效果也起到了很重要的作用。下面来看一下它们的效果。还在前面的程序中进行操作。单击界面上那个分隔符Spacer,当时将其属性中的sizeHint的高度设置为100,可是实际界面上的分隔符高度并没有到达100。这时可以看到它的sizeType属性设置为Expanding,如果将它更改为Fixed,这样界面上的分隔符马上增高了,现在它的实际高度才是sizeHint的高度值。

下面再来了解一下伸缩因子(stretch factor)的概念。前面讲垂直布局管理器时曾提到过它,其实它是用来设置部件间比例的。界面上的字体选择框和一个按钮处于一个水平布局管理器中,现在想让它们的宽度比例为2∶1,那么就可以单击对象栏中的horizontalLayout水平布局管理器对象,然后在它的属性栏中将layoutStretch 属性设置为“2,1”,这样这个水平布局管理器中的两个部件的宽度就是2:1的比例了。如果要在代码中进行设置,则可以在使用布局管理器的addWidget()函数添加部件的同时,在第二个参数中指定伸缩因子。
现在再来看一下窗体布局管理器中的一些属性。单击对象栏中的formLayout,其属性栏中几个属性的说明如下表所列。对于layoutFieldGrowthPolicy属性,这里选择ExpandingFieldsGrow选项,这样性别和年龄两个输入框就没有那么宽了,更符合美观要求。然后将界面中的“邮箱”标签更改为“邮箱地址”,在 layoutLabelAlignment属性中选择AlignRight。

【QT编程】QT布局管理_第3张图片
下面来看一下QWidget类及其子类部件的设置大小的相关属性。单击主界面,查看一下其属性栏,其最开始便是几个与大小有关的属性。这里的高度与宽度属性是现在界面的大小;下面的sizePolicy属性可以设置大小策略以及伸缩因子; minimumSize属性用来设置最小值,这里改为200×150; maximumSize属性设置最大值,将其设置为500×350 ; sizeIncrement属性和 baseSize属性是设置窗口改变大小的,一般不用设置,如下图所示。
【QT编程】QT布局管理_第4张图片
最后看一下布局管理器的 layoutSizeConstraint属性,它是用来约束窗口大小的,也就是说,这个只对顶级布局管理器有用,因为它只对窗口有用,对其他子部件没有效果。它的几个值及其含义如下表所列。这个属性的默认值是SetDefaultCon-straint。可以将界面的顶级布局管理器设置为SetFixedSize,这样运行程序可以看到,窗口就无法再变化大小了。

【QT编程】QT布局管理_第5张图片

05、可扩展窗口

一个窗口可能有很多选项是扩充的,只有在必要的时候才显示出来,这时就可以使用一个按钮来隐藏或者显示多余的内容,就是所谓的可扩展窗口。要实现可扩展窗口,就要得力于布局管理器的特性,那就是当子部件隐藏时,布局管理器自动缩小,当子部件重新显示时,布局管理器再次放大。下面看一个具体的例子。
依然在前面的程序中进行更改。首先将界面上的 pushButton显示文本更改为“显示可扩展窗口”,并在其属性栏选中 checkable选项。然后转到它的 toggled(bool)信号的槽,更改如下:

void MyWidget::on_pushButton_toggled(bool checked)  //显示窗口按钮
{
	ui->textEdit->setVisible(checked);  //设置文本编辑器的显示和隐藏
	if(checked)
	{
		ui->pushButton->setText(tr("隐藏可扩展窗口"));
	} else {
		ui->pushButton->setText(tr("显示可扩展窗口"));
	}
}

ps:这里使用按钮的按下与否两种状态来设置文本编辑器是否显示,并且相应地更改按钮中的文本。为了让文本编辑器在一开始是隐藏的,还要在MyWidget类的构造函数中添加一行代码:

ui->textEdit->hide();   //让文本编辑器隐藏,也可以使用setVisible(false)函数

这是运行程序,可扩展窗口隐藏时与显示的效果图如下:
【QT编程】QT布局管理_第6张图片
或者参考Qt欢迎界面的示例程序:Extension Example。

06、分裂器(QSplitter)

分裂器QSplitter类提供了一个分裂器部件。和QBoxLayout类似,可以完成布局管理器的功能,但是包含在它里面的部件,默认是可以随着分裂器的大小变化而变化的。比如一个按钮放在布局管理器中,它的垂直方向默认是不会被拉伸的,但是放到分裂器中就可以被拉伸。还有一点不同就是,布局管理器继承自QObject类,而分裂器却是继承自QFrame类,QFrame类又继承自QWidget类,也就是说,分裂器拥有QWidget类的特性,它是可见的,而且可以像QFrame 一样设置边框。

看个例子:
新建Qt Widgets应用,项目名称为mysplitter,基类选择QWidget,类名设为MyWidget。建好项目后打开 mywidget.ui文件,然后往界面上拖人4个Push Button,同时选中这4个按钮,右击并在弹出的级联菜单中选择“布局→使用分裂器水平布局”,将这4个按钮放到一个分裂器中。将分裂器拉大点,并在属性栏中设置其frameShape为Box,frameShadow为 Raised,lineWidth为5。此时运行程序,效果如图所示。

【QT编程】QT布局管理_第7张图片

07、设置伙伴(buddy)

前面讲述窗体布局管理器时提到了设置一个标签和一个部件的伙伴关系。其实,伙伴(buddy)是在QLabel类中提出的一个概念。因为一个标签经常用作一个交互式部件的说明,就像在讲窗体布局管理器时看到的那样,一个 lineEdit部件前面有一个标签说明这个lineEdit的作用。为了方便定位,QLabel提供了一个有用的机制,那就是提供了助记符来定位键盘焦点到对应的部件上,而这个部件就叫这个QLabel的伙伴。其中,助记符就是我们所说的加速键。使用英文标签时,在字符串的一个字母前面添加“&”符号,就可以指定这个标签的加速键是Alt加上这个字母;对于中文,需要在小括号中指定加速键字母,这个前面已经见过多次了。

Qt设计器中也提供了伙伴设计模式,下面看一个例子。

新建Qt Widgets应用,项目名称为mybuddy ,基类选择QWidget ,类名设为MyWidget。完成后打开 mywidget. ui文件,往界面上拖放4个标签Label,再在标签后面依次放上 PushButton,CheckBox,LineEdit和SpinBox。然后将PushButton前面的标签文本改为“&.Button:”, CheckBox前面的标签文本改为“C&.heckBox:”,LineEdit前面的标签文本改为“行编辑器(&L):”,SpinBox前面的标签文本改为“数字选择框(&N):”。单击设计器上方边栏中的编辑伙伴图标进入伙伴设计模式,分别将各个标签与它们后面的部件关联起来,如下图所示。然后按下F3键回到正常编辑模式,可以看到所有的&符号都不显示了。

【QT编程】QT布局管理_第8张图片
现在运行程序,按下Alt + B组合键,则可以看到按钮被按下了,而字母下面多了一个横杠,表示这个标签的加速键就是Alt加这个字母。
如果要在代码中设置伙伴关系,则只需要使用QLabel的setBuddy()函数就可以了。

08、Tab键顺序

对于一个应用程序,有时总希望使用Tab键将焦点从一个部件移动到下一个部件。在设计模式中,设计器提供了Tab键的设置功能。在前面程序的设计模式中,按下上方边栏的编辑Tab顺序按钮进入编辑Tab键顺序模式,这时已经显示出了各个部件的Tab键顺序,只需要单击这些数字就可以更改顺序。设置好之后,可以运行一下程序测试效果。需要说明,当程序启动时,焦点会在Tab键顺序为1的部件上。这里进行的设置等价于在 MyWidget类的构造函数中使用如下代码:

setTabOrder(ui->lineEdit,ui->spinBox);  //lineEdit在spinBox前面
setTabOrder(ui->spinBox,ui->pushButton);  //spinBox在pushButton前面
setTabOrder(ui->pushButton,ui->checkBox);  //pushButton在checkBox前面

09、布局管理小结

关于Qt布局管理,这点东西肯定只是基础,要想学习好布局,还得多加练习,边练习边总结。
本章内容,部分来自《Qt Creator快速入门》一书。新手入手Qt,这本书讲的是非常的全面的。

版权声明:转载请注明出处,谢谢。

你可能感兴趣的:(QT,qt,Qt学习)