一、描述
QLayout 类是布局管理器的基类,是 QBoxLayout、QGridLayout、QFormLayout 和 QStackedLayout 继承的抽象基类。
要自定义布局管理器,须实现函数:
- addItem()
- sizeHint()
- setGeometry()
- itemAt()
- takeAt()
还应该实现 minimumSize() 以确保如果空间太少,布局不会调整为零大小。要支持高度取决于宽度的子项,须实现 hasHeightForWidth() 和 heightForWidth()。
删除布局管理器后,布局管理(几何形状管理)将停止。
二、类型成员
1、enum QLayout::SizeConstraint:布局的调整大小模式。
- SetDefaultConstraint:小部件的最小尺寸设置为 minimumSize(),除非小部件已经具有最小尺寸。
- SetFixedSize:部件的尺寸设置为 sizeHint(),无法调整大小。
- SetMinimumSize:部件的最小尺寸设置为 minimumSize(),它不能更小。
- SetMaximumSize:部件的最大尺寸设置为 maximumSize(),它不能更大。
- SetMinAndMaxSize:部件的最小尺寸设置为 minimumSize(),其最大尺寸设置为 maximumSize()。
- SetNoConstraint:小部件不受约束。
三、属性成员
1、sizeConstraint : SizeConstraint
布局的调整大小模式。默认模式是 SetDefaultConstraint。
2、spacing : int
布局内小部件之间的间距。
如果没有显式设置值,则布局的间距继承自父布局,或者继承自父窗口小部件的样式设置。
对于 QGridLayout 和 QFormLayout,可以使用 setHorizontalSpacing() 和 setVerticalSpacing() 设置不同的水平和垂直间距。 在这种情况下,spacing() 返回 -1。
四、成员函数
1、QLayout(QWidget *parent = nullptr)
构造一个新的* QLayout。
布局直接设置为父级的*布局。一个小部件只能有一个*布局。它由 QWidget::layout() 返回。
如果 parent 为 nullptr,则必须将此布局插入另一个布局,或使用 QWidget::setLayout() 将其设置为小部件的布局。
2、bool activate()
如有必要,重做 parentWidget() 的布局。
通常不需要调用它,因为它会在最合适的时间自动调用。如果布局已重做,则返回 true。
3、void addChildLayout(QLayout *l)
从子类中的 addLayout() 或 insertLayout() 函数调用此函数,以将布局 l 添加为子布局。
唯一需要直接调用它的场景是实现支持嵌套布局的自定义布局。
4、void addChildWidget(QWidget *w)
从子类中的 addWidget() 函数调用此函数,以将 w 添加为布局的托管小部件。
如果 w 已经由布局管理,则此函数将发出警告并从该布局中删除 w。 因此,必须在将 w 添加到布局的数据结构之前调用此函数。
5、【纯虚函数】void addItem(QLayoutItem*item)
在子类中实现以添加项目。如何添加它是特定于每个子类的。
此函数通常不会在应用程序代码中调用,要将小部件添加到布局,使用 addWidget() 函数;要添加子布局,使用相关 QLayout 子类提供的 addLayout() 函数。
项目的所有权转移到布局,布局负责删除它。
6、void addWidget(QWidget *w)
以特定于布局的方式将小部件 w 添加到此布局。
7、QRect alignmentRect(const QRect &r)
返回当此布局的几何设置为 r 时应覆盖的矩形,前提是此布局支持 setAlignment()。
8、【static】QSize closestAcceptableSize(const QWidget *widget, const QSize &size)
返回满足小部件所有尺寸约束的尺寸。
9、QMargins contentsMargins()
返回布局周围使用的边距。默认使用样式提供的值。
在大多数平台上,所有方向的默认边距都是 11 像素。
void getContentsMargins(int *left, int *top, int *right, int *bottom)
对于不是 nullptr 的 left、top、right 和 bottom 中的每一个,存储指针所指位置中指定的边距大小。
void setContentsMargins(int left, int top, int right, int bottom)
void setContentsMargins(const QMargins &margins)
设置要在布局周围使用的边距。默认使用样式提供的值。
在大多数平台上,所有方向的边距都是 11 像素。
- QStyle::PM_LayoutLeftMargin:QLayout 的默认左边距。
- QStyle::PM_LayoutTopMargin:QLayout 的默认上边距。
- QStyle::PM_LayoutRightMargin:QLayout 的默认右边距。
- QStyle::PM_LayoutBottomMargin:QLayout 的默认下边距。
- QStyle::PM_LayoutHorizontalSpacing:QLayout 的默认水平间距。
- QStyle::PM_LayoutVerticalSpacing:QLayout 的默认垂直间距。
void unsetContentsMargins()
取消设置布局周围的任何用户定义的边距。布局将使用样式提供的默认值。
10、QRect contentsRect()
返回布局的 geometry() 矩形,且考虑内容边距。
11、【纯虚函数】int count()
返回布局中的项目数。
12、int indexOf(const QWidget *widget)
在此布局中搜索小部件(不包括子布局)。返回小部件的索引,如果未找到,则返回 -1。
13、int indexOf(const QLayoutItem *layoutItem)
在此布局中搜索布局项 layoutItem(不包括子布局)。返回 layoutItem 的索引,如果未找到 ,则返回 -1。
14、bool isEnabled()
是否启用了布局。
void setEnabled(bool enable)
设置是否禁用布局。
启用的布局会根据变化动态调整;禁用的布局就像它不存在一样(没有了布局,所有控件堆叠在一起)。
15、【纯虚函数】QLayoutItem * itemAt(int index)
必须在子类中实现以返回索引处的布局项。如果没有这样的项目,该函数必须返回 nullptr。项目从 0 开始连续编号。如果一个项目被删除,其他项目将重新编号。
此函数可用于迭代布局。以下代码将为小部件布局结构中的每个布局项绘制一个矩形:
static void paintLayout(QPainter *painter, QLayoutItem *item)
{
QLayout *layout = item->layout();
if (layout) {
for (int i = 0; i < layout->count(); ++i)
paintLayout(painter, layout->itemAt(i));
}
painter->drawRect(item->geometry());
}
void MyWidget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
if (layout())
paintLayout(&painter, layout());
}
16、void setMenuBar(QWidget *widget) / QWidget * menuBar()
通知几何管理器将widget放置在 parentWidget() 的顶部,在 QWidget::contentsMargins() 之外(即widget不受Margins设置的影响)。所有子小部件都放置在菜单栏的底部边缘下方。
#include <QApplication>
#include <QFormLayout>
#include <QLineEdit>
#include <QLabel>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QFormLayout * layout = new QFormLayout;
layout->addRow("label1",new QLineEdit);
layout->addRow("label2",new QLineEdit);
layout->setMenuBar(new QLabel ("我是菜单栏"));
QWidget w;
w.setLayout(layout);
w.show();
return a.exec();
}
17、QWidget * parentWidget()
返回此布局的父小部件,如果此布局未安装在任何小部件上,则返回 nullptr。
如果布局是子布局,则此函数返回父布局的父窗口小部件。
上面16的例子:
qDebug()<<&w<<layout->parent()<<layout->parentWidget();
void update()
更新 parentWidget() 的布局。通常不需要调用它,因为它会在最合适的时间自动调用。
18、void removeItem(QLayoutItem *item)
从布局中移除布局项。调用者有责任删除该项目。
19、void removeWidget(QWidget *widget)
从布局中移除widget。在此调用之后,调用者有责任管理 widget。
20、QLayoutItem * replaceWidget(QWidget *from, QWidget *to, Qt::FindChildOptions options = Qt::FindChildrenRecursively)
搜索小部件 from,如果找到则将其替换为小部件 to 。从成功返回包含小部件的布局项。否则返回 nullptr。
如果 options 包含 Qt::FindChildrenRecursively(默认),则搜索子布局以进行替换。选项中的任何其他标志都将被忽略。
返回的布局项不再归布局所有,应该删除或插入到另一个布局中。from 不再由布局管理,可能需要删除或隐藏。from 的父级保持不变。
此功能适用于内置 Qt 布局,但可能不适用于自定义布局。
enum Qt::FindChildOption:
- Qt::FindDirectChildrenOnly:查找对象的直接子项。
- Qt::FindChildrenRecursively:查找对象的所有孩子(递归搜索)。
21、bool setAlignment(QWidget *w, Qt::Alignment alignment)
bool setAlignment(QLayout *l, Qt::Alignment alignment)
设置对齐方式。如果在此布局中找到 w,则返回 true(不包括子布局), 否则返回false。
22、【纯虚函数】QLayoutItem * takeAt(int index)
必须在子类中实现以从布局中删除索引处的布局项目,并返回该项目。如果没有这样的项目,该函数必须什么都不做并返回nullptr。项目从0开始连续编号。如果一个项目被删除,其他项目将重新编号。
以下代码片段显示了从布局中删除所有项目的安全方法:
QLayoutItem *child;
while ((child = layout->takeAt(0)) != nullptr) {
...
delete child->widget(); // delete the widget
delete child; // delete the layout item
}