马上就要十一了,在这里小豆君先祝大家双节快乐,希望大家假期玩儿的开心!同时,小豆君也要带着家人去旅游啦,本篇文章也是十一前最后一篇了,等放假结束,小豆君再和大家见面。
本篇文章也算是布局管理器中比较重要的一篇了,尤其是布局管理的原理,还是希望大家能认真看一下。好了,下面我们进入正题。
3.1.6 栈布局管理器
栈布局可以添加很多窗口,但是在同一时刻,只能有一个窗口可以显示。
1 count:栈布局中的窗口数量,可以使用addWidget() insertWidget()添加窗口。
2 currentIndex:当前的窗口索引。
3 stackingMode:显示模式。
- StackOne:只有当前的窗口是可见的。
- StackAll:所有窗口都可见,但只有当前窗口在最上面。
主要代码示例
QLabel *firstPageWidget = new QLabel("first1"); QLabel *secondPageWidget = new QLabel("first2"); QLabel *thirdPageWidget = new QLabel("first3"); QStackedLayout *stackedLayout = new QStackedLayout; stackedLayout->addWidget(firstPageWidget); stackedLayout->addWidget(secondPageWidget); stackedLayout->addWidget(thirdPageWidget); ui->combo_page->addItem(tr("Page 1")); ui->combo_page->addItem(tr("Page 2")); ui->combo_page->addItem(tr("Page 3")); connect(ui->combo_page, SIGNAL(activated(int)), stackedLayout, SLOT(setCurrentIndex(int))); mainLayout->addLayout(stackedLayout);
3.1.7 QSpacerItem
当主窗口的大小改变时,有些地方就会出现空白区域,那使用QSpacerItem就可以将空白区域填充,否则有的控件就可能会被拉伸,影响美观。
下图是将一个按钮放入到了一个水平布局器中,但按钮被拉伸,按钮太长不美观。
下图是加入了一个水平的QSpacerItem的效果
在程序运行后,QSpacerItem会显示空白,设计器中的显示的弹簧效果只是为了区分它是一个QSpacerItem。
3.1.8 布局管理器的工作原理
当我们查看QLayout类时,会发现它是直接继承自QObject和QLayoutItem,由此可见,它并不是一个真正的窗口对象。
当主窗口大小改变时,那么主窗口做以下事情:
1 获取每个控件所设置的大小策略及大小约束,重新计算它们所需要的矩形区域;
2 调用每个控件的setGeometry()调整在主窗口上的位置和大小。
因此,在视觉上,当改变主窗口大小时,就像有一只魔术师的手在重新摆放每个控件。
由此我们推出以下3点重要内容
1 当使用布局时,不需要在构建子部件时传递父对象。布局将会自动地将这些子部件(使用QWidget::setParent())设置为所装布局窗口的子部件,因为布局本身并不是一个窗口,从某种意义上讲,它其实就是一个计算子控件矩形区域的工具,布局器从属于主窗口。
2 sizePolicy QSizePolicy:大小策略,该属性属于QWidget。
凡是继承自QWidget的窗口,都有此大小策略,所以主窗口的布局器才可以调整每个控件的矩形区域。
(1) sizeHint 推荐大小提示
在QWidget中还有一个属性叫作sizeHint,Qt中的帮助文档是这样说的
This property holds the recommended size for the widget.If the value of this property is an invalid size, no size is recommended.The default implementation of sizeHint() returns an invalid size if there is no layout for this widget, and returns the layout's preferred size otherwise.
那么翻译过来是这样的
这个属性保存了一个窗口的推荐大小。如果这个值是无效的,那么没有可推荐的窗口大小。如果这个窗口没有设置布局,则默认会返回一个无效的QSize,如果设置了布局,就返回这个窗口推荐的QSize。
那么,如果这么翻译过来,可能还是不太明白这到底是个什么意思。
好,我们来抓关键一句话,如果设置布局,那就返回推荐大小。
我们知道Qt的所有窗口控件都是继承自QWidget的,并且这个属性对应的成员函数是虚函数,
也就是说所有控件都是可以返回自己的推荐大小,那么,我们试想QLabel,它希望返回的大小提示肯定是,水平方向上让所有的文字刚好都可以显示在屏幕上,垂直方向上固定不变,所以它在水平方向上会返回一个不小于文字像素的长度,当然,如果文字太长,就需要另外的策略了。
所以这个sizeHint会根据不同控件的功能,来提供它们默认的大小策略。
另外,还有一个属性叫minimumSizeHint,它和sizeHint很像,你可以像我上面的分析一样,看一下它的描述。
由此,我们引出下一条
(2) Qt针对不同的控件,根据它们所具有的功能,默认使用了不同的大小策略。
- QWidget,QFrame等容器控件在垂直和水平方向都使用Preferred,这意味着窗口在两个方向可以自由调整大小,但更趋向于sizeHint()的返回值。
- QLabel, QPushButton,QLineEdit类似于长条形状的控件的大小策略是,可以水平拉伸,垂直固定。
- QToolButton通常是正方形的,所以允许双向的增长。
- 支持不同方向的控件(如QSlider、QScrollBar或QHeader)只在各自的方向上指定拉伸。
- 可以提供滚动条的控件(通常是QScrollArea的子类)倾向于指定它们可以使用扩展的空间。
(3) 针对不同的需求,Qt为此定下了不同的大小策略类型。
以下可同时适用于水平和垂直方向
- Fixed:sizeHint()是唯一可以接受的选择,窗口不能增长或缩小(例如按钮的垂直方向)。
- Minimum:sizeHint()是最小的,窗口可以被扩展,但是扩展后并不美观(例如按钮的水平方向,最小是文字像素,如果随着父窗口的扩展而扩展,就会显得不美观)。
- Maximum:sizeHint()是最大的。如果其他控件需要空间(例如分隔线),该控件可以收缩。
- Preferred:sizeHint()是最好的,控件可以缩小,也可以扩展(QWidge默认的t策略)。
- Expanding:sizeHint()是一个合理的大小,但是控件可以缩小。最重要的,控件当它的父窗口变大时,它应该得到尽可能多的空间(例如水平滑块的水平方向)。
- MinimumExpanding:同Expanding,但不能再缩小。
- Ignored:sizeHint()将被忽略。控件将获得尽可能多的空间。
3 QLayout::SizeConstraint:大小约束条件,该属性属于QLayout。
当窗口改变大小时,布局本身也会跟着变化,本属性就描述了布局变化时的大小限制,其实就是计算方式的限制。
以下的主窗口指的是,布局所在的窗口。
- SetDefaultConstraint:主窗口最小值设置为minimumSize(),除非已经具有最小值。
- SetNoConstraint:窗口不受最大最小限制
- SetMinimumSize:主窗口最小值设置为minimumSize(),无法再缩小。
- SetFixedSize:主窗口大小被设置为sizeHint(),大小不能再改变。
- SetMaximumSize:主窗口最大值设置为maximumSize(),无法再变大。
- SetMinAndMaxSize:主窗口的最小值设置为minimumSize(),最大值设置为maximumSize()。
如果有的同学想加深印象,可以查看一下Qt提供的自定义布局的例子,FlowLayout和BorderLayout,这两个例子已经非常好了,这里我就不举例了。
下面是一个弹出窗口的例子
3.1.9 弹出窗口
新建gui项目PopWidget项目,类名PopWidget,基类为QWidget
在ui中拖入一个QLineEdit,一个QPushButton,一个QTextEdit。
QPushButton属性设置checkable设置为true
popwidget.ui
popwidget.h
#ifndef POPWIDGET_H #define POPWIDGET_H #include <QWidget> namespace Ui { class PopWidget; } class PopWidget : public QWidget { Q_OBJECT public: explicit PopWidget(QWidget *parent = 0); ~PopWidget(); private slots: void on_pushButton_toggled(bool checked); private: Ui::PopWidget *ui; }; #endif // POPWIDGET_H
popwidget.cpp
#include "popwidget.h" #include "ui_popwidget.h" PopWidget::PopWidget(QWidget *parent) : QWidget(parent), ui(new Ui::PopWidget) { ui->setupUi(this); ui->textEdit->hide(); ui->verticalLayout->setSizeConstraint(QLayout::SetFixedSize); } PopWidget::~PopWidget() { delete ui; } void PopWidget::on_pushButton_toggled(bool checked) { ui->textEdit->setVisible(checked); if (checked) { ui->pushButton->setText("收回"); } else { ui->pushButton->setText("弹出"); } }
编译运行程序,如下图,textEdit可以被弹出和收回
好了,标准布局器就讲到这里啦。
想要第一时间看到小豆君的更新,请关注微信公众号:小豆君,只要关注,便可加入小豆君为大家创建的C++\Qt交流群,方便讨论学习。