目录
- 一、QGridLayout布局规则
- 二、创建QGridLayout
- 三、成员函数
- 1. 控件间距
- 2. 可拉伸控件(弹簧)
- 3. 最小行高/列宽
- 4. 行数和列数
- 5. 锁定纵横比
- 6. 添加控件
- 7. 添加布局
- 8. 设置栅格布局原点位置
- 9. 操作布局项
- 9.1 访问布局项
- 9.2 删除布局项
- 9.3 通过索引获取布局项位置信息
- 9.4 获取布局项数量
与QBoxLayout
只能在一个方向布局不同,QGridLayout
可以在网格中布局(垂直和水平两个方向)。
这里仅以按钮为例,布局也可用于其他控件。
一、QGridLayout布局规则
与QBoxLayout
类似,详见 QBoxLayout布局规则
二、创建QGridLayout
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);
三、成员函数
1. 控件间距
和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; // 获取两个方向的间距
2. 可拉伸控件(弹簧)
同样和QBoxLayout
类似,参考 可拉伸控件 ,相关函数如下:
void setRowStretch(int row, int stretch); // 设置指定行的弹簧系数
void setColumnStretch(int column, int stretch); // 设置指定列的弹簧系数
int rowStretch(int row) const; // 获取指定行的弹簧系数
int columnStretch(int column) const; // 获取指定列的弹簧系数
3. 最小行高/列宽
void setRowMinimumHeight(int row, int minSize); // 设置最小行高
void setColumnMinimumWidth(int column, int minSize); // 设置最小列宽
int rowMinimumHeight(int row) const; // 获取最小行高
int columnMinimumWidth(int column) const; // 获取最小列宽
4. 行数和列数
int columnCount() const; // 获取列数
int rowCount() const; // 获取行数
5. 锁定纵横比
根据宽度计算高度
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;
}
6. 添加控件
// 在控件队列最后面添加一个新控件
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
,则控件所占控件一直延申到最右和最底部边界,如下:
7. 添加布局
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
类似,这里不再赘述。
8. 设置栅格布局原点位置
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
左上角,如下图:
右上角如下图,其他方向同理:
9. 操作布局项
Qt提供了一个布局项的抽象类QLayoutItem
,提供了对布局中单元格的操作。
这里仅介绍QGridLayout
直接涉及到的几个方法,关于QLayoutItem
更详细的描述见
9.1 访问布局项
QLayoutItem *itemAt(int index) const override;
QLayoutItem *itemAtPosition(int row, int column) const;
可以通过索引访问,也可以通过所在行列位置访问。
默认计数都是从0开始,需要注意的是,index
的方式是从远离原点的位置开始计数,行列定位的则是从靠近原点的位置开始计数,如下:
index
方式:(测试发现的,不知道为什么要这么设计,和习惯用法不同,如果你知道原因欢迎评论区留言)
行列方式:
9.2 删除布局项
QLayoutItem *takeAt(int index) override;
这个只能通过索引定位,索引计数方法同上。
9.3 通过索引获取布局项位置信息
void getItemPosition(int idx, int *row, int *column, int *rowSpan, int *columnSpan) const;
9.4 获取布局项数量
int count() const override;