在迄今为止讲到每一个例子中,我们只是简单的把窗口部件放置到某个确定的布局中。但在某些情况下,由此形成的布局看起来可能还不是我们最想要的形式。在这些情形中,可以通过改变要摆放的窗口部件的大小策略和大小提示来调整布局。
1.大小提示(size hint)和最小大小提示(minimum size hint)
在介绍Qt窗口部件的大小策略之前,首先介绍大小提示(size hint)和最小大小提示(minimum size hint)。
⑴ 大小提示
大小提示是Qt为一个窗口部件推荐的尺寸。当Qt GUI窗口部件进行初始化时,将通过QWidget::sizeHint()来获得窗口部件的大小提示,这是一个虚函数,它的原型为:
virtual QSize sizeHint () const
在未被重载的情况下,它的返回值是这样的:
◆ 如果该窗口部件不属于任何布局管理器,那么该函数将返回一个无效的值;
◆ 如果该窗口部件属于某个布局管理器,那么该函数将返回一个该布局管理器认为比较合适的尺寸。
⑵ 最小大小提示
最小大小提示(minimum size hint)是Qt为窗口部件推荐的最小尺寸,它的使用规则是:
如果需要绘制的窗口部件的尺寸(包括长和高两个方面)小于其最小提示(这在Qt Designer中往往表现为有些被压缩的看不到它的内容),并且该窗口部件的最小提示在最大尺寸和最小尺寸允许的范围内,那么该窗口部件显示的尺寸将是其最小提示的值。
设置窗口部件的最小大小提示是通过QWidget::minimumSizeHint()完成的。它的返回值有如下情景:
◆ 如果该窗口部件没有布局管理器,该函数返回一个无效的值;
◆ 如果该窗口部件属于某个布局管理器,该函数返回布局管理器认为合适的一个尺寸。
2.大小策略(size policy)
一个窗口部件的大小策略会告诉布局系统应该如何对它进行拉伸或收缩。Qt为它所有的内置窗口部件都提供了合理的默认大小策略值,但是由于不可能为每一种可能产生的布局都提供唯一的默认值,所以在一个窗体中,开发人员改变它上面的一个或两个窗口部件的大小策略是非常普遍的现象。一个QSizePolicy既包含一个水平分量也包含一个垂直分量。以下是一些常用的取值:
表11-1 枚举值QSizePolicy::Policy的内容
枚举常量 |
值 |
说明 |
QSizePolicy::Fixed |
0 |
大小提示是该窗口部件的唯一尺寸选择,所以它不会发生任何的伸缩。 |
QSizePolicy::Minimum |
GrowFlag |
大小提示是该窗口部件的最小尺寸,它不会变得更小,但它可以变得更大,不过采用该策略的窗口部件在“争夺”空间上不占优势。 |
QSizePolicy::Maximum |
ShrinkFlag |
大小提示是该窗口部件的最大尺寸,也就是该窗口部件不会比大小提示的尺寸更大。该窗口部件可以在没有受到其它窗口部件“要求”的情况下,自由的缩小尺寸。 |
QSizePolicy::Preferred |
GrowFlag | ShrinkFlag |
一般情况下,该窗口部件会将大小提示作为它的优先和最佳选择,但它也可以变得足够的小,也可以变大,但不占优势。该策略是QWidget窗口部件默认的策略。 |
QSizePolicy::Expanding |
GrowFlag | ShrinkFlag | ExpandFlag |
采用该策略的窗口部件也能够感觉到尺寸提示,但是它倾向于尽可能的占用更大的空间,该窗口部件也可以变得足够小。 |
QSizePolicy::MinimumExpanding |
GrowFlag | ExpandFlag |
大小提示将是该窗口部件的最小尺寸,该窗口部件将尽可能的占用更多的空间。该策略已经不再被推荐使用,建议用Expanding替代它,并且重载minimumSizeHint()。 |
QSizePolicy::Ignored |
ShrinkFlag | GrowFlag | IgnoreFlag |
与Expanding有些相似,只是所有的大小提示都被忽略,该窗口部件将会尽可能的占用空间。 |
表11-1中的“值”这一列实际上告诉了我们每一种策略一般是具有“倾向性”的,比如QSizePolicy::Fixed的值为0,则它“倾向于”保持自己的大小不变,即保持大小提示的尺寸。而QSizePolicy::Expanding的值是3个值的叠加,总的“倾向性”是趋于占用更多空间的,等等。这就为当多个具有不同大小策略的窗口部件放置在一起时,如何判断它们占用空间的模式提供了基本的判断依据,以下是几种常见的组合。
◆ 相同大小策略的窗口部件被布局管理器组合在一起。在这种情况下,除了窗口部件不能超出它的大小范围外,不同的窗口部件可以按自己的伸缩因子在其允许的范围内自由的伸缩。
◆ QSizePolicy::Fixed和任何其他的大小策略组合在一起。
具有QSizePolicy::Fixed大小策略的窗口部件其大小是不变的,即保持在sizeHint()大小,而其他的窗口部件可以在允许的范围内自由伸缩。
◆ QSizePolicy::Preferred和QSizePolicy::Expanding组合在一起。
具有QSizePolicy::Preferred尺寸策略的窗口部件其大小是不变的,即它认为大小提示是最适合它的,而其他的窗口部件大小可以在其允许的范围内自由伸缩。
◆ QSizePolicy::Ignored和其他尺寸策略(QSizePolicy::Fixed策略除外)组合在一起的时候,不同的窗口部件在各自允许的范围内自由伸缩。
◆ QSizePolicy::Preferred,QSizePolicy::Minimum和QSizePolicy::Maximum组合在一起的时候,各窗口部件在各自允许的范围内可以自由伸缩。
3.伸缩因子(stretch factor)
除了大小策略中包含的水平方向和垂直方向两个分量之外,QSizePolicy类还保存了水平方向和垂直方向的一个伸缩因子。这些伸缩因子可以用来说明在增大窗体时,对不同的子窗口部件应使用的不同放大比例。即需要设置QSizePolicy::horizontalStretch和QSizePolicy::verticalStretch的值来实现。默认情况下,被布局管理器组合在一起的窗口部件的伸缩因子是相等的,都为0。此时,在所有的窗口部件都没有超出各自的大小范围允许的情况下,窗口部件的大小始终相等。
例如,假定在一个QListWidget的右面还有一个QTextEdit,并且希望这个QTextEdit的长度能够是QListWidget长度的两倍,那么就可以把这个QTextEdit在水平方向上的拉伸因子(QSizePolicy::horizontalStretch)设置为2,而把QListWidget在水平方向上的拉伸因子(QSizePolicy::horizontalStretch)设置为1;垂直方向上保持默认为0,即两者一样的高。这样设置的效果如图11-10所示。
4.大小约束(size constraint)
影响布局方式的另一种方法是设置它的子窗口部件的最大大小、最小大小或固定大小。这些是通过设置sizeConstraint属性来完成的。该属性值是一个枚举常量,定义了布局的大小约束的模式。表列出了它所有可能的取值,它的默认值是QLayout::SetDefaultConstraint。获取和设置该属性值可以通过QWidget::layout()来获取主窗口部件的布局管理器,然后可以调用QLayout::sizeConstraint()函数来查看当前的设置情况,然后再通过QLayout::setSizeConstraint()函数来设置该布局管理器的sizeConstraint属性。这两种函数的原型如下:
SizeConstraint sizeConstraint () const
void setSizeConstraint ( SizeConstraint )
其中,SizeConstraint的取值即是在表11-2中的枚举值的范围内。
表11-2 布局管理器的大小约束属性(QLayout::SizeConstraint)可能的取值
常量 |
值 |
说明 |
QLayout::SetDefaultConstraint |
0 |
主窗口部件的最小尺寸设置为minimumSize(),除非该窗口部件已经有一个最小尺寸 |
QLayout::SetFixedSize |
3 |
主窗口部件的尺寸设置为sizeHint(),并且不允许改变该窗口部件的尺寸 |
QLayout::SetMinimumSize |
2 |
主窗口部件的最小尺寸设置为minimumSize(),并且该窗口部件不能够变得更小 |
QLayout::SetMaximumSize |
4 |
主窗口部件的最大尺寸设置为maximumSize(),并且该窗口部件不能够变得更大 |
QLayout::SetMinAndMaxSize |
5 |
主窗口部件的最小尺寸设置为minimumSize(),最大尺寸设置为maximumSize() |
QLayout::SetNoConstraint |
1 |
主窗口部件的大小不会受到约束 |
5.空白(margin)和间距(spacing)
每种布局都有两个重要的属性,空白和间距。空白指的是整个布局四周距离窗体边缘的距离;间距指的是布局管理器内部各个窗口部件之间的距离。
空白属性即margin(),间距属性即spacing(),它们的默认值是有窗体的风格决定的。Qt的默认风格下,子窗体部件的margin()的值是9英寸,窗体的margin()值是11英寸。spacing()的值与margin()相同。
如果要设置这两个值可以通过setMargin()和setSpacing()。
注意,从Qt4.3开始,margin()属性已经逐渐不再被Qt4所推荐,更好的设置空白的方法是使用setContentsMargins()方法,它的原型如下:
void QLayout::setContentsMargins ( int left, int top, int right, int bottom )
其中,left, top, right, 和 bottom表示环绕在布局周围的空白。
对于QGridLayout 和QFormLayout,不要使用setSpacing()方法,而是要分别使用setHorizontalSpacing()和setVerticalSpacing()方法来设置水平和垂直方向的间距。如果你使用了setSpacing()方法,获取spacing()时,它的返回值将为-1。