[QT

您所在的位置:网站首页 缺省按钮是什么意思 [QT

[QT

2024-01-04 22:18| 来源: 网络整理| 查看: 265

本文转自:《Qt编程指南》        作者:奇先生

Qt编程指南,Qt新手教程,Qt Programming Guide

6.5 控件尺寸调整策略

基于 QWidget 的控件都会继承 sizePolicy 属性( QSizePolicy 类型),这个属性包括两个大的方面内容:伸展因子 (Stretch Factor)和 伸展策略(Policy),这些都会影响到界面最终的布局显示。我们本节先大致介绍布局器的工作原理,然后分两小节讲解伸展因子、伸展策略以及 QSizePolicy 类其他内容,并通过 Qt 设计师进行一些控件伸展因子设置的示范,最后是两个尺寸调整策略设置的示例。  

6.5.1 布局器工作原理

当添加控件到布局器时,布局器的工作原理如下: (1)所有的控件初始时,布局器根据控件自己的 QWidget::sizePolicy() 和  QWidget::sizeHint(),分配相应的空间给各个控件。sizePolicy() 就是控件的尺寸调整策略,比如 QSizePolicy::Fixed 就是不拉伸,空间就是固定的,而 QSizePolicy::Expanding 就是尽可能占据空间,死劲拉伸。sizeHint() 就是控件本身的建议尺寸,或叫最佳尺寸,这个建议尺寸是 Qt 类库自己根据需要显示的内容计算的,所有的控件和窗体都能自己计算建议尺寸。 (2)如果有控件自己设置了大于零的伸展因子(stretch factors),那么在主界面窗口变大时,新增的空闲区域按照控件的伸展因子比例进行分配。伸展因子的内容在下面 6.5.2 小节专门讲解。 (3)如果有控件的伸展因子设置为 0,那么这个控件会尽量不占用窗口变大后的空闲区域,如果其他控件都不想要空闲区域,伸展因子为 0 的控件才会去尝试占据窗口变大后的空闲区域。默认情况下,所有控件的伸展因子其实都是 0,这时候布局器会优先拉伸尺寸策略为 QSizePolicy::Expanding 的控件。 (4)当窗口缩小时,布局器会根据控件的最小尺寸限定控件尺寸下限,控件到达它的最小尺寸后就不会继续缩小。最小尺寸可以是 minimumSize 指定的最小尺寸,如果没设置 minimumSize ,那么最小尺寸是 minimumSizeHint 指定的最小建议尺寸,minimumSizeHint 是 Qt 类库自己计算的,一般不需要程序员设置。(有些特殊情况,如果控件尺寸仅仅由伸展因子 stretch factor 决定,那么就没有最小尺寸和最小建议尺寸)。 (5)当窗口变大时,布局器会根据控件的最大尺寸限定控件的尺寸上限,控件达到它的最大尺寸后就不再增长。最大尺寸由控件的 maximumSize 指定。(有些特殊情况,如果控件尺寸仅仅由伸展因子 stretch factor 决定,那么就没有最大尺寸)。 上面是 Qt 帮助文档内容的翻译和解释,我们现在稍微归纳一下布局器中影响控件拉伸的因素:① 最小尺寸和最大尺寸,控件尺寸会限定在最小尺寸和最大尺寸之间。② 建议尺寸 QWidget::sizeHint(),这个建议尺寸是后续尺寸调整的基础,在布局时会先给控件分配建议尺寸的空间。③ 伸展因子(stretch factors),根据伸展因子的比例分配新增的空闲空间给各个控件。④ 尺寸策略 QWidget::sizePolicy(),在上述处理之后,那么再根据各个控件的尺寸调整策略决定控件应该尽可能拉伸还是尽量不拉伸。 这些规律对水平布局器、垂直布局器、网格布局器都是通用的。比较例外的是表单布局器,表单布局器在垂直方向不拉伸,第一列的标签也不拉伸,受尺寸调整策略影响的只 有第二列的域在水平方向的拉伸行为。 在影响界面布局的因素中,最小尺寸和最大尺寸可以直接设置控件的 minimumSize 和 maximumSize 属性,对应的函数为:

void setMinimumSize(const QSize &)       //最小尺寸 void setMinimumSize(int minw, int minh)  //最小尺寸 void setMaximumSize(const QSize &)       //最大尺寸 void setMaximumSize(int maxw, int maxh)  //最大尺寸

这些函数和属性我们在 6.1.1 小节专门介绍过,设置最小尺寸和最大尺寸是没啥技术含量的,比较简单,这里不赘述了。建议尺寸 QWidget::sizeHint() 通常是 Qt 类库自己根据需要显示的内容计算的,并没有直接的设置函数,只能用 QWidget::sizeHint() 函数获取建议的尺寸。如果程序员不自己定制新的控件类和布局器类,是不需要操心建议尺寸的。 影响控件拉伸的四个因素中,头两个因素通常都比较简单不用操心,因此我们本节就主要学习伸展因子和尺寸调整策略。  

6.5.2 QSizePolicy 之一:伸展因子

控件和水平布局器、垂直布局器、网格布局器都可以设置伸展因子。窗口拉伸时,布局器会根据每个控件或子布局器的水平和垂直方向的伸展因子,分配新增的空闲空间。例外的是如果控件设置了 sizePolicy 属性里的策略为 QSizePolicy::Fixed 固定高度或固定宽度,那就不拉伸控件,只拉伸控件之间的间隙。对于固定宽度或高度的控件,没什么好讨论,因为它们不拉伸。我们下面考虑会拉伸的情形。 本小节是通过三个 ui 文件示范的,没有用到新项目。读者可以从如下网址获取 ui 文本:stretchfactors 下载 threebuttons.ui、fourbuttons.ui、fourlayouts.ui 三个文件,然后可以用 Qt 设计师或 QtCreator 打开它们,根据下面的示范操作这些界面文件。

(1)控件本身的水平和垂直伸展因子

通常控件都是从 QWidget 直接或间接派生的,都可以设置 sizePolicy 属性,在 Qt 设计师或 QtCreator 设计模式,可以在右下角属性编辑栏看到选中控件或窗体的 sizePolicy 属性:

上图标出的就是 sizePolicy 属性,里面分为四个小属性,"水平策略" 和 "垂直策略" 就是下一小节介绍的伸展策略,"水平伸展" 和 "垂直伸展" 就是本小节的伸展因子。 以三个按钮控件为例,如果它们的伸展因子都是 0,那么三个按钮在水平布局里就是均匀拉伸:

如果把 "One" 按钮的 "水平伸展" 设为 1,"Two" 按钮的 "水平伸展" 设为 2,"Three" 按钮的 "水平伸展" 设为 3,那么在窗口拉大时,该行三个按钮的伸展因子之和为 1+2+3 == 6,新的空间就按照 1/6 ,2/6 ,3/6 的比例划分给这三个按钮,显示效果就如下面这样:

如果把 "One" 按钮的 "水平伸展" 设为 2,"Two" 按钮的 "水平伸展" 设为 4,"Three" 按钮的 "水平伸展" 设为 0,那么在窗口拉大时,分配规律就是:先计算伸展因子之和 2+4+0 == 6,新的空间按照 2/6 ,4/6,0/6 的比例划分给这三个按钮,显示效果如下:

因为第三个按钮的伸展因子是 0,第三个按钮会保持一个建议尺寸,其他两个按钮会根据伸展因子的占比进行拉伸。三个水平伸展因子为 2、4、0,其实也可以直接写成 1、2、0,两种是等价的,不管有没有公约数。 通过设计师或 QtCreator 设计模式修改伸展因子是很简单的,如果要通过代码来修改,那么可以用类似下面的代码:

    //获取旧的尺寸策略作为底板,修改需要变动的伸展因子 QSizePolicy sp = ui->pushButton1->sizePolicy(); sp.setHorizontalStretch(2); //水平伸展因子 sp.setVerticalStretch(0); //垂直伸展因子 //把新策略设置给按钮1 ui->pushButton1->setSizePolicy(sp);

其他类型的控件代码也可类似的编写,先获取旧的策略,在旧策略基础上修改我们需要变动的伸展因子。设置水平伸展因子的函数声明为:

void QSizePolicy::​setHorizontalStretch(int stretchFactor)

设置垂直伸展因子的函数声明为:

void QSizePolicy::​setVerticalStretch(int stretchFactor)

注意 stretchFactor 的取值范围是 0 到 255,负数就当做 0,大于 255 就当做 255,因此设置超出范围的数也没意义。一般用个位数 的伸展因子就够用了,伸展因子没必要弄太大。除了控件自身可以设置伸展因子,布局器也可以为内部直属的控件或子布局器设置伸展因子。如果布局器和内部直属的控件都设置了伸展因子,那么布局器的设置会覆盖直属控件的伸展因子。因此不建议直接设置控件自己的伸展因子属性,而是通过布局器来设置各个子控件或子布局器的伸展因子。 另外,从设计上看,控件只能管自己的局部矩形,控件不知道自己的伸展因子会对相邻控件造成多大影响,控件自身没有宏观的概念。尤其是网格布局器,某一行某一列的控 件设置伸展因子,会影响到全部网格的控件排列,如果每行的控件都设置一些乱七八糟的伸展因子,那么整个网格的布局就无法预料了。 我们应该从布局器的角度考虑界面划分,布局器则通常管理多个控件的一大片区域,通过布局器来设置各个子条目的伸展因子,就能从宏观角度合理分配空间,决定各个子条 目按多大的比例进行拉伸。

(2)水平和垂直布局器的伸展因子设置

QHBoxLayout 和 QVBoxLayout 都是通过基类 QBoxLayout 的函数设置内部直属的各个控件和子布局的伸展因子,对应的设置函数为:

void setStretch(int index, int stretch) bool setStretchFactor(QWidget * widget, int stretch) bool setStretchFactor(QLayout * layout, int stretch)

第一个函数是设置序号为 index 的控件或子布局的伸展因子。 第二个函数是设置布局器内部 widget 控件的伸展因子,使用这个函数设置伸展因子会覆盖控件自身原来设置的伸展因子属性。这个函数仅仅设置直属的子控件,该布局器的子布局器内部的孙子控件是不管的。如果设置成 功就返回 true,如果 widget 不是该布局器的直属子控件,那么会返回 false。 第三个函数是设置内部子布局器 layout 的伸展因子。这个函数也是设置直属的子布局器,而在子布局器内部的孙子布局器是不管的。如果设置正确就返回 true,否则返回 false。 如果要获取某个序号的控件或子布局器的伸展因子是多少,可以用如下函数:

int stretch(int index) const

在设计师或 QtCreator 设计模式,选中某个水平或垂直布局器,可以在右下角设置布局器的属性栏:

选中布局器之后,右下角属性编辑栏可以看到 layoutStretch 一栏,里面是英文逗号分隔的数字,对应三个按钮的情况,默认就是0,0,0;数字的个数与直属的子控件和子布局器总共的计数是一致的,分别与各个序号的子控件和子布局对应。在上图中,如果把 layoutStretch 设置为(注意是英文逗号)1,2,3;那么显示效果就是:

如果把 layoutStretch 设置为1,2,0那么显示效果就变成:

我们这里都是拿水平布局器作为例子示范,主要是因为很多控件的水平伸展策略都是可以拉伸的。 而按钮控件,默认在垂直方向上的伸展策略是 QSizePolicy::Fixed ,按钮的高度是固定的,所以没有拿垂直布局器举例。在控件不能拉伸的情况,设置伸展因子就没有用:

上面都是以功能控件举例的,控件通过 sizePolicy 属性控制伸展策略,可以限定控件为固定高度等等。如果是子布局器,那么子布局器在水平和垂直方向通常都是可以拉伸的。因此伸展因子对直属的子布局器总是有效的,而对固定高度或固定宽度的控件会出现失效的情况。

(3)网格布局器的伸展因子设置

网格布局器本身是二维的,它会始终保持控件在行和列上的对齐。不建议直接设置网格布局器内部控件的伸展因子属性,因为改变一个控件的伸展因子属性就会影响到全部的网格布局。应该通过网格布局器的函数或属性来设置行或列的伸展因子。 网格布局器为了保持网格的对齐特性,它都是整行或者整列第设置伸展因子:

void setRowStretch(int row, int stretch)       //设置整行的伸展因子 void setColumnStretch(int column, int stretch) //设置整列的伸展因子

另外还可以设置某个整行的最小高度,或者设置某个整列的最小宽度:

void setRowMinimumHeight(int row, int minSize)      //第 row 行最小高度设置为 minSize void setColumnMinimumWidth(int column, int minSize) //第 column 列的最小宽度设置为 minSize

在设计师或 QtCreator 设计模式,可以设置网格布局器对应的四个特有属性,如下所示:

layoutRowStretch 就是各个行对应的伸展因子; layoutColumnStretch 就是各个列对应的伸展因子; layoutRowMinimumHeight 是各个行对应的最小高度; layoutColumnMinimumWidth 是各个列对应的最小宽度。 如果我们把两个列的伸展因子调整为1,3那么,得到效果就是:

如果控件的宽度或者高度为固定的,那么网格控件也不会拉伸控件,比如上面按钮的高度就是固定的,没有被拉伸。在控件高度都不能拉伸时,设置网格布局器各个行的伸展因子也没意义,比如下图:

在上图里,虽然设置了 layoutRowStretch 为3,1但是两行的占比其实是一样的,因为两行的控件在垂直方向都不能拉伸,垂直伸展因子就没效果。如果上面四个格子不是按钮控件,而是四个子布局器,那么两个方向的伸展因子都会生效:

上图四个大格子,每个格子里都是水平布局器,每个水平布局器里放一个标签和一个按钮。 每个格子都是子布局器的情况下,我们看到列的比例是 1:3 ,行的比例是 3:1 ,和右下角设置的比例就完全对上了。 网格布局器的伸展因子设置就介绍到这,作为对比,我们提一下表单布局器。表单布局器因为第一列宽度固定,并且在垂直方向不拉伸,所以没有设置伸展因子的函数和属性,它只有设置域列增长策略的函数:

void QFormLayout::setFieldGrowthPolicy(FieldGrowthPolicy policy)

QFormLayout::setFieldGrowthPolicy() 我们在 6.4.1 小节讲过了,感兴趣的读者可以去回顾一下,这里不重复介绍了。 实际的布局中,其实伸展因子用的比较少,因为很少有遇到控件必须按照某些比例来拉伸的,尤其是控件的类型不同时,设置不同种类的控件拉伸比例,通常没多大意义。实 际编程中最常用的是伸展策略。只有实际的功能控件有伸展策略相关的函数和属性,布局器是没有自己独立的伸展策略的。 对于伸展因子和伸展策略的运用,我们这里建议一个大致的分工原则: 在实际布局中,如果要控制某个布局器直属的子布局器、控件之间的拉伸比例,就通过布局器的伸展因子来设置; 如果要控制功能控件是尽量拉伸还是尽量固定,那么通过控件自己的伸展策略属性来设置。  

6.5.3 QSizePolicy 之二:伸展策略

控件的 sizePolicy 属性包括两方面内容,上面介绍了第一方面的伸展因子,本小节是第二方面的伸展策略:

属性编辑栏里的水平策略和垂直策略就是本小节讲解的伸展策略。伸展策略应用最多,也最复杂。 QSizePolicy 关于伸展策略的内容可以分为两个层级:

(1)策略的基本标志位

由 QSizePolicy::​PolicyFlag 类型枚举,包括四个基本标志位:

枚举标志位数值描述QSizePolicy::GrowFlag1可增长标志,如果有必要的话,可以在建议尺寸之外继续增长。QSizePolicy::ExpandFlag2尽量扩展标志,能占多大空间就占多大。QSizePolicy::ShrinkFlag4可收缩标志,如果有必要的话,可以在缩小到建议尺寸之后继续缩小。QSizePolicy::IgnoreFlag8忽略建议尺寸,这个增长方式最野蛮,能占多大空间就占多大空间

建议尺寸就是通过控件的 sizeHint() 函数获取的尺寸,这个尺寸通常由 Qt 类库自己根据要显示的内容计算。建议尺寸是伸展策略的基准。 控件通常不会直接设置策略的基本标志位,因为没有这方面的设置函数。基本标志位的用途,是为了组合成为实用的策略枚举常量,也就是下面第二层级的内容。

(2)策略的枚举常量

伸展策略的枚举常量由 QSizePolicy::​Policy 类型枚举,有七个定义好的常量,用于设置控件的水平和垂直伸展策略:

枚举常量数值拉伸特点描述QSizePolicy::Fixed0固定以建议尺寸固定住,对于水平方向是固定宽度,垂直方向是固定高度。QSizePolicy::MinimumGrowFlag被动拉大以建议尺寸为最小尺寸,如果有多余的空间就拉伸,没有多余的空间就保持建议尺寸。被动扩张。QSizePolicy::MaximumShrinkFlag被动缩小以建议尺寸为最大尺寸,窗口缩小时,如果其他控件需要,该控件可以尽量缩小为其他控件腾出空间。QSizePolicy::PreferredGrowFlag | ShrinkFlag被动伸缩以建议尺寸为最佳尺寸,能屈能伸,窗口缩小时可以为其他控件腾出空间,窗口变大时,也可以占据其他控件不需要的空闲空间。基类 QWidget 默认是这种策略。被动扩张。QSizePolicy::ExpandingGrowFlag | ShrinkFlag | ExpandFlag主动扩张建议尺寸仅仅是明智的建议,但控件基本不采用。这个模式也是能屈能伸,但它倾向于主动扩张,它会尽可能占据新增的区域。QSizePolicy::MinimumExpandingGrowFlag | ExpandFlag主动扩张以建议尺寸作为最小尺寸,主动扩张,尽可能占据新增的区域。QSizePolicy::IgnoredShrinkFlag | GrowFlag | IgnoreFlag野蛮扩张忽略建议尺寸,虽然能屈能伸,但是它会尽最大可能占据空间。

我们对七个策略常量大致分两类,第一类是固定、单向缩小、单向拉大的,相同布局情景中,占据的尺寸大小排序为:

QSizePolicy::Maximum ≤ QSizePolicy::Fixed ≤ QSizePolicy::Minimum ≤ QSizePolicy::MinimumExpanding 。

第二类是能屈能伸的,如果在相同布局情景中,占据尺寸大小排序为:

QSizePolicy::Preferred ≤ QSizePolicy::Expanding ≤ QSizePolicy::Ignored 。

七个策略枚举常量,最常用到的只有如下四个,我们考虑它们在相同布局场景中,占据的尺寸大小进行不严格排序(有例外):

QSizePolicy::Fixed ≤ QSizePolicy::Preferred ≈ QSizePolicy::Minimum ≤ QSizePolicy::Expanding

虽然 Preferred 和 Expanding 都是能屈能伸的类型,但实际情况是只有窗口缩小到特别小的情况,这两个才会比 Fixed 小。 窗口如果特别小,那么窗口的可用性显然受限,这通常属于不合理的设置,因此正常情况下不会遇到 Preferred 和 Expanding 比 Fixed 占用空间小的情况。 以上的策略枚举常量是用于尺寸策略的设置函数中,控件和窗口的伸展策略细分为水平方向和垂直方向,通过如下两个函数分别设置:

void QSizePolicy::​setHorizontalPolicy(Policy policy)  //设置水平策略 void QSizePolicy::​setVerticalPolicy(Policy policy)    //设置垂直策略

水平和垂直策略在大多数情况下都是不相关的,各自管各自的维度。除了调用函数,设计师和 QtCreator 设计模式也可以直接设置控件的 sizePolicy 属性两个子属性:"水平策略" 和 "垂直策略" 。 伸展策略的常量有七个,每个常量都有各自的特性,我们在这里把它们简化一下,在实际使用中可以按照下面三条建议来运用策略的枚举常量:① 如果希望控件尺寸在水平或垂直方向固定住,那么把该维度的策略设置为 QSizePolicy::Fixed。 ② 如果希望控件被动拉伸,其他控件不需要空间时这个控件才会占据新增区域,那么可以用 QSizePolicy::Preferred (尺寸下限是隐含的最小建议尺寸)或者 QSizePolicy::Minimum(尺寸下限是建议尺寸)。 ③ 如果希望控件尽量拉伸,主动扩张,那就把策略设置为 QSizePolicy::Expanding。 Qt 里面的控件默认策略也是基本符合上面三条建议的,所以希望大家记住这三条建议,因为比较实用。  

6.5.4 QSizePolicy 之三:其他内容

QSizePolicy 除了上面两小节的伸展因子和伸展策略,还有一些其他的内容,这部分补充内容应用会比较少,但是会影响界面的一些细节,有必要在这讲一下。

(1)控件类型设置

QSizePolicy::ControlType 枚举类型有一大堆枚举常量,大部分的 Qt 控件都对应一个枚举常量,比如按压按钮对应的常量为 QSizePolicy::PushButton,单行编辑控件对应的枚举常量是 QSizePolicy::LineEdit,类似的还 有很多,这里不列举了。 QSizePolicy 类中关于控件类型获取和设置的函数为:

ControlType QSizePolicy::​controlType() const void QSizePolicy::​setControlType(ControlType type)

这个控件类型应用比较少,不是什么时候都生效的,而且对界面布局影响很小,只是一些细节有差异。控件类型只会被一些特定的 Qt 界面风格(可以查询 QStyle 类文档)采用,比如苹果系统风格的 QMacStyle,不同的控件类型会影响各个控件之间的默认间隙。比如 Mac OS X Aqua 指导方针中指出按压按钮之间需要 12 像素的间隙,而垂直方向排布的单选按钮间隔是 6 像素。因为控件类型影响很小,所以通常可以忽略这个设置。

(2)建议尺寸的宽度和高度相关性设置

多数情况下建议尺寸  sizeHint() 的高度和宽度是不相关的,但有些特殊情况,比如能够自动换行的标签控件、菜单栏(后面章节讲解),比如一行长文本自动换行变成两行时,高度是双倍的,如果把标签拉宽,当两 行文本恢复成一行的时候,高度就变成单行的。这种控件越宽,它高度相对低一些,越窄,高度就高一些。因此这些控件的建议尺寸计算时,高度和宽度是相关的。 可以通过如下函数设置在计算建议尺寸时,高度和宽度相关:

void QSizePolicy::​setHeightForWidth(bool dependent)   //设置高度依赖宽度

dependent 如果为 true,那么控件的建议尺寸高度就和宽度相关。如果 dependent 为 false 那么就是无关的。 如果要获知建议尺寸的高度是否与宽度相关,可以用如下函数:

bool QSizePolicy::​hasHeightForWidth() const        //判断高度是否依赖宽度

另外还有一对相反功能的函数,计算建议尺寸时,宽度可能会依赖高度,这个设置只对 QGraphicsLayout 的子类有用,一般是用不到的:

void QSizePolicy::​setWidthForHeight(bool dependent)  //设置宽度依赖高度 bool QSizePolicy::​hasWidthForHeight() const          //判断宽度是否依赖高度

HeightForWidth 和 WidthForHeight 二者最多只能有一个生效,不能双向依赖的。 注意无论是 HeightForWidth 还是 WidthForHeight ,都只对建议尺寸的计算有影响,不会直接影响窗口或控件的高度和宽度拉伸比例。如果希望窗口或控件的高度和宽度保持一定比例,比如 2 : 3 ,那么这些函数是完全没用的,因为根本不是一个概念。

(3)控件隐藏时是否仍然占据布局空间

程序运行时,控件都可以通过函数 hide() 隐藏自己。在控件隐藏时,控件是否还占据布局器里的空间,这是可以设置的:

void QSizePolicy::​setRetainSizeWhenHidden(bool retainSize)  //设置控件在隐藏时是否仍占据布局器空间 bool QSizePolicy::​retainSizeWhenHidden() const     //判断隐藏控件是否占据布局器空间

默认情况下,控件调用 hide() 隐藏之后,就不会在通过布局器分配空间了,因为没有必要。 如果遇到特殊情况需要保留隐藏控件在布局器里的占用的空间,可以用上述函数设置。 如果设置保留隐藏控件的空间,那么布局器会留下一块空白区域,就是控件在隐藏前应该占据的区域。

(4)水平和垂直方向的设置互换

为了应对可能的屏幕旋转操作,QSizePolicy 提供了一个快捷函数,能够把水平方向的伸展因子、伸展策略与垂直方向上的伸展因子、伸展策略完全互换过来:

void QSizePolicy::​transpose()

这个函数读者可以根据实际情况试试。 关于控件的尺寸调整策略就介绍这么多,下面通过两个例子试一试伸展因子和伸展策略的功效。  

6.5.5 伸展策略对比示例

这一小节通过两个窗口来对比常用到的四个伸展策略枚举常量,主界面的窗口里面是六个按钮,点击里面的第一个按钮会弹出第二个示范窗口,第二个示范窗口里面放置六个 单行编辑控件。两个窗口的布局器和各个控件的水平伸展策略都是一样的,我们一方面对比四个常用策略的拉伸特性,另一方面对比按钮和单行编辑控件对布局器和策略的不 同反应。 打开 QtCreator,新建一个 Qt Widgets Application 项目,在新建项目的向导里填写: ①项目名称 comparepolicies,创建路径 D:\QtProjects\ch06,点击下一步; ②套件选择里面选择全部套件,点击下一步; ③基类选择 QWidget,点击下一步; ④项目管理不修改,点击完成。 建好项目之后,打开窗体 widget.ui 文件,进入设计模式,按照下图拖入六个按钮:

我们按从上到下、从左到右顺序说明一下六个按钮的属性: ① 文本 "Fixed" ,对象名称 pushButtonFixed ,水平策略选择 Fixed 。 ② 文本 "Preferred" ,对象名称 pushButtonPreferred,水平策略选择 Preferred 。 ③ 文本 "Preferred2" ,对象名称 pushButtonPreferred2,水平策略选择 Preferred 。 ④ 文本 "Minimum" ,对象名称 pushButtonMinimum,水平策略选择 Minimum 。 ⑤ 文本 "Minimum2" ,对象名称 pushButtonMinimum2,水平策略选择 Minimum 。 ⑥ 文本 "Expanding" ,对象名称 pushButtonExpanding,水平策略选择 Expanding 。 设置好六个按钮的属性之后,我们对每个行进行布局,先对第一行两个按钮水平布局,第二行和第三行也一样用水平布局,得到的效果如下:

然后我们点击主窗体空白区域,不选中任何控件和子布局器(其实就是唯一选中主界面窗口自身),直接点击上面的垂直布局按钮,自动为窗口设置主布局器:

这样主界面的布局就设置完毕。下面我们要为第一个 "Fixed" 按钮添加一个 clicked() 信号的槽函数,等会我们在槽函数添加代码来弹出第二个示范窗口:

添加好槽函数之后,保存界面文件,我们回到代码编辑模式,首先是编辑主窗体头文件 widget.h ,我们要为第二个示范窗口添加成员指针和创建第二个示范窗口的函数:

#ifndef WIDGET_H #define WIDGET_H #include namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private slots: void on_pushButtonFixed_clicked(); private: Ui::Widget *ui; //第二个示范窗口,全部放置 QLineEdit QWidget *m_pWidget; //通过代码构造第二个示范窗口 void CreateWidget(); }; #endif // WIDGET_H

m_pWidget 是我们自己用代码构造的第二个示范窗口,CreateWidget() 就是负责构造第二个示范窗口的函数。头文件里其他代码行都是自动添加的。 主窗体的界面不需要调整,我们刚才在设计模式都设置好了。我们下面编辑源代码文件 widget.cpp 主要是为了构建第二个示范窗口的内容,并通过 "Fixed" 按钮的槽函数弹窗显示。 在 widget.cpp 文件中,首先是头文件包含和主窗体的构造函数:

#include "widget.h" #include "ui_widget.h" #include //单行编辑器 #include //水平布局器 #include //垂直布局器 #include Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); //按钮的建议尺寸和最小建议尺寸 qDebug()sizePolicy(); //修改第一个的水平策略为 Fixed sp.setHorizontalPolicy(QSizePolicy::Fixed); leFixed->setSizePolicy(sp); //第二个编辑器 QLineEdit *lePreferred = new QLineEdit(m_pWidget); lePreferred->setText(tr("Preferred")); sp = lePreferred->sizePolicy(); //修改第二个的水平策略为 Preferred sp.setHorizontalPolicy(QSizePolicy::Preferred); lePreferred->setSizePolicy(sp); //第一行的布局器 QHBoxLayout *lay1 = new QHBoxLayout(); lay1->addWidget(leFixed); //添加第一个编辑器 lay1->addWidget(lePreferred); //添加第二个编辑器 //把第一行的布局器添加到主布局器 mainLayout->addLayout(lay1); //待续

第一个单行编辑器新建时是指定 m_pWidget 为父窗口,这样该控件会由 m_pWidget 窗口管理。 然后设置第一个单行编辑器的文本为 "Fixed" ,并把水平策略修改为 QSizePolicy::Fixed 。 第一个编辑器的尺寸会固定为建议尺寸,不会被拉宽。 第二个单行编辑器新建时也是指定 m_pWidget 为父窗口,然后设置文本为 "Preferred",修改水平策略为 QSizePolicy::Preferred,这个编辑器会被动地拉大或缩小。虽然没有指定该编辑器最小尺寸,但是等会程序运行时我们会看到 "Preferred" 编辑器以隐含的最小建议尺寸为下限。 然后我们新建了第一行的水平布局器 lay1,注意这个布局器没有指定父窗口。 我们把第一行的两个编辑器添加给 lay1 ,然后把 lay1 添加到主布局器。 下面看看第二行控件和布局器的代码:

   //第二行 //第三个编辑器 QLineEdit *lePreferred2 = new QLineEdit(m_pWidget); lePreferred2->setText(tr("Preferred2")); sp = lePreferred->sizePolicy(); //修改第三个的水平策略为 Preferred sp.setHorizontalPolicy(QSizePolicy::Preferred); lePreferred2->setSizePolicy(sp); //第四个编辑器 QLineEdit *leMinimum = new QLineEdit(m_pWidget); leMinimum->setText(tr("Minimum")); sp = leMinimum->sizePolicy(); //修改第三个的水平策略为 Minimum sp.setHorizontalPolicy(QSizePolicy::Minimum); leMinimum->setSizePolicy(sp); //第二行的布局器 QHBoxLayout *lay2 = new QHBoxLayout(); lay2->addWidget(lePreferred2); lay2->addWidget(leMinimum); //添加到主布局器 mainLayout->addLayout(lay2); //待续

第三个单行编辑器也是以 m_pWidget 为父窗口,设置文本为 "Preferred2",修改水平策略为 QSizePolicy::Preferred。 第四个单行编辑器也是以 m_pWidget 为父窗口,设置文本为 "Minimum",修改水平策略为 QSizePolicy::Minimum。 然后新建了第二行的布局器 lay2 ,这个布局器没有指定父窗口指针。 接着将 lePreferred2 和 leMinimum 两个编辑器添加给布局器 lay2 ,再把第二行布局器 lay2 添加到主布局器 mainLayout 。 接下来是第三行控件和布局器的代码:

    //第三行 //第五个编辑器 QLineEdit *leMinimum2 = new QLineEdit(m_pWidget); leMinimum2->setText(tr("Minimum2")); sp = leMinimum2->sizePolicy(); //修改第五个的水平策略为 Minimum sp.setHorizontalPolicy(QSizePolicy::Minimum); leMinimum2->setSizePolicy(sp); //第六个编辑器 QLineEdit *leExpanding = new QLineEdit(m_pWidget); leExpanding->setText(tr("Expanding")); sp = leExpanding->sizePolicy(); //修改第六个的水平策略为 Expanding sp.setHorizontalPolicy(QSizePolicy::Expanding); leExpanding->setSizePolicy(sp); //第三行的布局器 QHBoxLayout *lay3 = new QHBoxLayout(); lay3->addWidget(leMinimum2); lay3->addWidget(leExpanding); mainLayout->addLayout(lay3); //待续

第五个单行编辑器也是以 m_pWidget 为父窗口,设置文本为 "Minimum2" ,修改水平策略为 QSizePolicy::Minimum。 第六个单行编辑器也是以 m_pWidget 为父窗口,设置文本为 "Expanding",修改水平策略为 QSizePolicy::Expanding。 然后新建了第三行的布局器 lay3 ,这个布局器没有指定父窗口。 接着把第三行的两个编辑器 leMinimum2、leExpanding 添加到 布局器 lay3 ,并把 lay3 添加到主布局器 mainLayout。 注意上面关于控件的代码写法: 单行编辑控件的父窗口是 m_pWidget ,而不是布局器,也不能是布局器。 布局器仅仅是辅助布局的手段,布局器不是实际的功能控件。 布局器基类是 QLayoutItem,不能独立存在,它需要依附于其他实体功能控件或窗口,但不会拥有任何控件,也就是不能作为父窗口。 实体功能控件的基类是 QWidget,可以独立存在,也可以借助布局器进行布局,QWidget 派生类控件可以作为其他控件的父窗口,可以拥有子控件。 CreateWidget() 函数最后一小部分代码是设置主布局器和打印调试信息的:

    //设置该窗口的主布局器 m_pWidget->setLayout(mainLayout); //如果只有一个布局器的 parent 设置为该窗口,那么可以不调用 setLayout() //上面的 setLayout() 一句其实可以省略,mainLayout 自动是主布局器 //打印信息 qDebug()


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3