赞
踩
与QBoxLayout
只能在一个方向布局不同,QGridLayout
可以在网格中布局(垂直和水平两个方向)。
这里仅以按钮为例,布局也可用于其他控件。
与QBoxLayout
类似,详见 QBoxLayout布局规则
QGridLayout
只有一个构造函数
explicit QGridLayout(QWidget *parent = nullptr);
可以通过拖动控件创建,也可以使用代码直接创建
由于布局是默认铺满父级Widget
的,为了方便控制布局的整体大小,一般不是将最外层的Widget
窗口传给QGridLayout
,而是再新建一个Widget
,如下:
// 创建指针
QWidget *gridLayoutWidget;
QGridLayout *gridLayout;
// 创建新Widget
gridLayoutWidget = new QWidget(Widget);
// 为新Widget设置大小
gridLayoutWidget->setGeometry(QRect(149, 80, 321, 191));
// 实例化布局对象,并将新Widget传入
gridLayout = new QGridLayout(gridLayoutWidget);
和QBoxLayout
类似,QGridLayout
也有间距的概念,不同是QGridLayout
可以设置两个方向的间距,如下:
void setHorizontalSpacing(int spacing); // 设置水平方向的间距
int horizontalSpacing() const; // 获取水平方向的间距
void setVerticalSpacing(int spacing); // 设置垂直方向的间距
int verticalSpacing() const; // 获取处置方向的间距
void setSpacing(int spacing) override; // 设置两个方向的间距
int spacing() const override; // 获取两个方向的间距
同样和QBoxLayout
类似,参考 可拉伸控件 ,相关函数如下:
void setRowStretch(int row, int stretch); // 设置指定行的弹簧系数
void setColumnStretch(int column, int stretch); // 设置指定列的弹簧系数
int rowStretch(int row) const; // 获取指定行的弹簧系数
int columnStretch(int column) const; // 获取指定列的弹簧系数
void setRowMinimumHeight(int row, int minSize); // 设置最小行高
void setColumnMinimumWidth(int column, int minSize); // 设置最小列宽
int rowMinimumHeight(int row) const; // 获取最小行高
int columnMinimumWidth(int column) const; // 获取最小列宽
int columnCount() const; // 获取列数
int rowCount() const; // 获取行数
根据宽度计算高度
bool hasHeightForWidth() const override;
int heightForWidth(int) const override;
int minimumHeightForWidth(int) const override;
这三个函数默认是没有实际功能的,如要使用,需要自己重载实现,他们的源码如下:
bool QLayoutItem::hasHeightForWidth() const
{
return false;
}
int QLayoutItem::heightForWidth(int /* w */) const
{
return -1;
}
int QLayoutItem::minimumHeightForWidth(int w) const
{
return heightForWidth(w);
}
官方给出了重载的例子,如下:
int MyLayout::heightForWidth(int w) const
{
if (cache_dirty || cached_width != w) {
MyLayout *that = const_cast<MyLayout *>(this);
int h = calculateHeightForWidth(w);
that->cached_hfw = h;
return h;
}
return cached_hfw;
}
// 在控件队列最后面添加一个新控件
inline void addWidget(QWidget *w) { QLayout::addWidget(w); }
// 在布局的指定位置添加一个新控件
void addWidget(QWidget *, int row, int column, Qt::Alignment = Qt::Alignment());
// 在布局的指定位置添加一个新控件,并可指定跨行/列
void addWidget(QWidget *, int row, int column, int rowSpan, int columnSpan, Qt::Alignment = Qt::Alignment());
其中,inline void addWidget(QWidget *w) { QLayout::addWidget(w); }
如果队列中间有空的位置,也会忽略过,只会在队列最后添加新控件,如下:
第三行第二列空出一个位置,添加控件后,跳过了该位置,如下:
如果想一个控件占多行/列,可以使用函数void addWidget(QWidget *, int row, int column, int rowSpan, int columnSpan, Qt::Alignment = Qt::Alignment());
,其中,参数row
和column
用以指定控件的位置,从0
开始计数,rowSpan
和columnSpan
指定从当前位置向右或向下所占的行和列数,如下:
原始布局,为了方便显示控件所占空间,将控件的sizePolicy
设置为Expanding
,使其充满布局单元格(关于sizePolicy
详见QGridLayout布局规则):
示例1:
在(2, 0)
的位置添加行控件,所占空间为1行1列,如下:
ui->gridLayout->addWidget(btn, 2, 0, 1, 1);
示例2:
在(2, 0)
的位置添加行控件,所占空间为2行1列,如下:
ui->gridLayout->addWidget(btn, 2, 0, 2, 1);
示例3:
如果rowSpan
和columnSpan
为-1
,则控件所占控件一直延申到最右和最底部边界,如下:
void addLayout(QLayout *, int row, int column, Qt::Alignment = Qt::Alignment());
void addLayout(QLayout *, int row, int column, int rowSpan, int columnSpan, Qt::Alignment = Qt::Alignment());
布局中还能嵌套布局,函数入参与使用方法和addWidget
类似,这里不再赘述。
void setOriginCorner(Qt::Corner);
Qt::Corner originCorner() const;
和QBoxLayout
的Direction
类似,设置布局中控件的排列方向。
其中,Qt::Corner
是一个枚举如下:
enum Corner {
TopLeftCorner = 0x00000,
TopRightCorner = 0x00001,
BottomLeftCorner = 0x00002,
BottomRightCorner = 0x00003
};
枚举 | 值 | 描述 |
---|---|---|
Qt::TopLeftCorner | 0x00000 | 矩形的左上角 |
Qt::TopRightCorner | 0x00001 | 矩形的右上角 |
Qt::BottomLeftCorner | 0x00002 | 矩形的左下角 |
Qt::BottomRightCorner | 0x00003 | 矩形的右上角 |
布局原点默认为Qt::TopLeftCorner
左上角,如下图:
右上角如下图,其他方向同理:
Qt提供了一个布局项的抽象类QLayoutItem
,提供了对布局中单元格的操作。
这里仅介绍QGridLayout
直接涉及到的几个方法,关于QLayoutItem
更详细的描述见
QLayoutItem *itemAt(int index) const override;
QLayoutItem *itemAtPosition(int row, int column) const;
可以通过索引访问,也可以通过所在行列位置访问。
默认计数都是从0开始,需要注意的是,index
的方式是从远离原点的位置开始计数,行列定位的则是从靠近原点的位置开始计数,如下:
index
方式:(测试发现的,不知道为什么要这么设计,和习惯用法不同,如果你知道原因欢迎评论区留言)
行列方式:
QLayoutItem *takeAt(int index) override;
这个只能通过索引定位,索引计数方法同上。
void getItemPosition(int idx, int *row, int *column, int *rowSpan, int *columnSpan) const;
int count() const override;
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。