00. 目录
文章目录
01. 概述
QGridLayout:格栅布局,也被称作网格布局(多行多列)。
栅格布局将位于其中的窗口部件放入一个网状的栅格之中。QGridLayout需要将提供给它的空间划分成的行和列,并把每个窗口部件插入并管理到正确的单元格。 栅格布局是这样工作的:
它计算了位于其中的空间,然后将它们合理的划分成若干个行(row)和列(column),并把每个由它管理的窗口部件放置在合适的单元之中,这里所指的单元(cell)即是指由行和列交叉所划分出来的空间。
在栅格布局中,行和列本质上是相同的,只是叫法不同而已。下面将重点讨论列,这些内容当然也适用于行。
在栅格布局中,每个列(以及行)都有一个最小宽度(使用setColumnMinimumWidth()设置)以及一个伸缩因子(使用setColumnStretch()设置)。最小宽度指的是位于该列中的窗口部件的最小的宽度,而伸缩因子决定了该列内的窗口部件能够获得多少空间。
02. 开发环境
Windows系统:Windows10
Qt版本:Qt5.15或者Qt6
03. 常用函数详解
QGridLayout 类将控件放置到网格中布局,它本身会从父窗口或父布局中占据尽可能多的界面空间,然后把自己的空间划分为行和列,再把每个控件塞到设置好的一个或多个单元格中。
QGridLayout 类既有控制行的函数,也有对应控制列的函数。对于列来说,有设置每列的最小宽度的函数:
void setColumnMinimumWidth(int column, int minSize)
如果要设置各个列在窗口变化时拉伸比例不同,可以用如下函数:
void setColumnStretch(int column, int stretch)
每列控件之间可以设置布局的水平间隙:
void setHorizontalSpacing(int spacing)
对于行,也都有类似的函数,只是把英文单词换一下:
void setRowMinimumHeight(int row, int minSize) //设置行最小高度
void setRowStretch(int row, int stretch) //设置行的伸展因子
void setHorizontalSpacing(int spacing) //设置行的垂直间隙
如果要添加控件或其他布局器、自定义布局条目,使用如下函数:
void addWidget(QWidget * widget, int row, int column, Qt::Alignment alignment = 0)
void addWidget(QWidget * widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment = 0)
void addLayout(QLayout * layout, int row, int column, Qt::Alignment alignment = 0)
void addLayout(QLayout * layout, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment = 0)
void addItem(QLayoutItem * item, int row, int column, int rowSpan = 1, int columnSpan = 1, Qt::Alignment alignment = 0)
函数第一个参数都是要添加的控件、布局器或自定义布局条目,
row 和 column 是左上角起始的单元格坐标,
如果没有指定 rowSpan 和 columnSpan 那么就是 1*1 的唯一单元格,
指定了 rowSpan 和 columnSpan 就会占据 rowSpan * columnSpan 的小矩形,占据连续多行多列单元格。
最后的 alignment 是控件或布局器、布局条目在单元格中的对齐方式,比如水平的左对齐、居中、右对齐,垂直方向顶部对齐、底部对齐、垂直居中等等,具体 的可以查 Qt 帮助文档。Qt 关于对齐方式的枚举常量都是通用的。
通常情况下 QGridLayout 不需要自己添加空白条 QSpacerItem,因为其他功能控件把各自的单元格占据之后,剩下没控件占据的单元格自然就是空的,空的格子默认里面什么都没有,也没有空白条。
如果要获知网格有多少行、有多少列(包括空的格子计数),使用如下函数:
int rowCount() const //行计数
int columnCount() const //列计数
如果要获取某个单元格的布局条目,使用:
QLayoutItem * itemAtPosition(int row, int column) const
注意,如果某个格子是全空的,也没有手动添加空白条,那么 itemAtPosition() 返回 NULL 指针。因此使用这个函数必须判断返回值是否为空。
rowCount * columnCount 是总共的单元格计数,但并不是控件或子布局的计数。控件或子布局的计数用重载的虚函数:
virtual int count() const
用 add* 函数添加控件或子布局时,每个控件或子布局都对应一个序号,这个序号与网格坐标是无关的,是由 add* 函数添加顺序决定的。
QGridLayout 提供了根据控件或子布局序号查询单元格位置、分布的函数(但没有反查序号的函数):
void getItemPosition(int index, int * row, int * column, int * rowSpan, int * columnSpan) const
getItemPosition() 函数会填充参数里的四个指针指向的变量,四个指针指向的变量就是 add* 函数里面指定的单元格坐标和分布。
根据控件或子布局的序号获取布局条目的函数为:
virtual QLayoutItem * itemAt(int index) const
根据控件序号可以从 QGridLayout 中移除布局条目:
virtual QLayoutItem * takeAt(int index)
凡是函数返回值为指针的都要判断是否为空指针,因为上面函数的序号如果超出范围,也会返回空指针。涉及到指针的操作一定要细心判断。
得到非空的 QLayoutItem 对象指针之后,就可以从 QLayoutItem 对象里提取实际的控件或布局器、空白条:
QWidget * QLayoutItem::widget()
QLayout * QLayoutItem::layout()
QSpacerItem * QLayoutItem::spacerItem()
另外如果是自己定制的 QLayoutItem 派生类对象,可以把获取的基类对象指针 QLayoutItem * ,通过 dynamic_cast 转成派生类对象指针试试。 注意判断函数返回的指针是否为空,非空指针才能进行下一步操作。
04. Qt设计师使用网格布局
第一种方式:选中所有需要使用网格布局的控件,然后鼠标右击选择布局,然后再选择网格布局。
第二种方式:选中所有需要使用网格布局的控件,然后在工具栏中选择使用网格布局。
05. 使用代码实现网格布局
程序示例一:
#include <QApplication>
#include <QGridLayout>
#include <QPushButton>
#include <QWidget>
#include <QObject>
#include <QDebug>
int main(int argc, char **argv)
{
QApplication a(argc, argv);
QWidget w;
//创建布局对象
QGridLayout *layout = new QGridLayout();
QPushButton *btn1 = new QPushButton;
btn1->setText("Test Button 1");
//设置组件大小可以扩展
btn1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
//设置最小尺寸
btn1->setMinimumSize(160, 30);
QPushButton *btn2 = new QPushButton;
btn2->setText("Test Button 2");
//设置组件大小可以扩展
btn2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
//设置最小尺寸
btn2->setMinimumSize(160, 30);
QPushButton *btn3 = new QPushButton;
btn3->setText("Test Button 3");
//设置组件大小可以扩展
btn3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
//设置最小尺寸
btn3->setMinimumSize(160, 30);
QPushButton *btn4 = new QPushButton;
btn4->setText("Test Button 4");
//设置组件大小可以扩展
btn4->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
//设置最小尺寸
btn4->setMinimumSize(160, 30);
//设置间距
layout->setSpacing(10);
//网格不同坐标添加不同的组件
layout->addWidget(btn1, 0, 0);
layout->addWidget(btn2, 0, 1);
layout->addWidget(btn3, 1, 0);
layout->addWidget(btn4, 1, 1);
//设置行列比例系数
layout->setRowStretch(0, 1);
layout->setRowStretch(1, 3);
layout->setColumnStretch(0, 1);
layout->setColumnStretch(1, 3);
w.setLayout(layout);
w.show();
return a.exec();
}
执行结果
程序示例二:
#include <QApplication>
#include <QGridLayout>
#include <QPushButton>
#include <QWidget>
#include <QObject>
#include <QDebug>
int main(int argc, char **argv)
{
QApplication a(argc, argv);
QWidget w;
//创建布局对象
QGridLayout *layout = new QGridLayout();
QPushButton *btn1 = new QPushButton("one");
QPushButton *btn2 = new QPushButton("two");
QPushButton *btn3 = new QPushButton("three");
QPushButton *btn4 = new QPushButton("four");
QPushButton *btn5 = new QPushButton("five");
layout->addWidget(btn1, 0, 0);
layout->addWidget(btn2, 0, 1);
layout->addWidget(btn3, 1, 0, 1, 2);
layout->addWidget(btn4, 2, 0);
layout->addWidget(btn5, 2, 1);
w.setLayout(layout);
w.show();
return a.exec();
}
执行结果
程序示例三:
#include <QApplication>
#include <QGridLayout>
#include <QPushButton>
#include <QWidget>
#include <QObject>
#include <QDebug>
int main(int argc, char **argv)
{
QApplication a(argc, argv);
QWidget w;
//创建布局对象
QGridLayout *layout = new QGridLayout();
QPushButton *btn1 = new QPushButton;
btn1->setText("Test Button 1");
//设置组件大小可以扩展
btn1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
//设置最小尺寸
btn1->setMinimumSize(160, 30);
QPushButton *btn2 = new QPushButton;
btn2->setText("Test Button 2");
//设置组件大小可以扩展
btn2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
//设置最小尺寸
btn2->setMinimumSize(160, 30);
QPushButton *btn3 = new QPushButton;
btn3->setText("Test Button 3");
//设置组件大小可以扩展
btn3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
//设置最小尺寸
btn3->setMinimumSize(160, 30);
QPushButton *btn4 = new QPushButton;
btn4->setText("Test Button 4");
//设置组件大小可以扩展
btn4->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
//设置最小尺寸
btn4->setMinimumSize(160, 30);
//设置间距
layout->setSpacing(10);
//网格不同坐标添加不同的组件
//坐标(0, 0)的组件占用两行一列
layout->addWidget(btn1, 0, 0, 2, 1);
//坐标(0, 1)的组件占用两行一列
layout->addWidget(btn2, 0, 1, 2, 1);
//坐标(2, 0)的组件占用一行两列
layout->addWidget(btn3, 2, 0, 1, 2);
//坐标(3, 0)的组件占用一行两列
layout->addWidget(btn4, 3, 0, 1, 2);
w.setLayout(layout);
w.show();
return a.exec();
}
执行结果
程序示例四:
#include <QApplication>
#include <QGridLayout>
#include <QVBoxLayout>
#include <QPushButton>
#include <QWidget>
#include <QObject>
#include <QDebug>
int main(int argc, char **argv)
{
QApplication a(argc, argv);
QWidget w;
//创建布局对象
QGridLayout *gLayout = new QGridLayout();
QVBoxLayout *vLayout = new QVBoxLayout();
QPushButton *btn1 = new QPushButton;
btn1->setText("Test Button 1");
//设置组件大小可以扩展
btn1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
//设置最小尺寸
btn1->setMinimumSize(160, 30);
QPushButton *btn2 = new QPushButton;
btn2->setText("Test Button 2");
//设置组件大小可以扩展
btn2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
//设置最小尺寸
btn2->setMinimumSize(160, 30);
QPushButton *btn3 = new QPushButton;
btn3->setText("Test Button 3");
//设置组件大小可以扩展
btn3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
//设置最小尺寸
btn3->setMinimumSize(160, 30);
QPushButton *btn4 = new QPushButton;
btn4->setText("Test Button 4");
//设置组件大小可以扩展
btn4->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
//设置最小尺寸
btn4->setMinimumSize(160, 30);
QPushButton *btn5 = new QPushButton;
btn5->setText("Test Button 5");
//设置组件大小可以扩展
btn5->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
//设置最小尺寸
btn5->setMinimumSize(160, 30);
gLayout->setSpacing(10);
//编号为1 2 3的进行网格布局
gLayout->addWidget(btn1, 0, 0);
gLayout->addWidget(btn2, 0, 1);
gLayout->addWidget(btn3, 1, 0);
//将编号为4 5的按钮添加到垂直布局器中
vLayout->addWidget(btn4);
vLayout->addWidget(btn5);
//布局管理器嵌套
gLayout->addLayout(vLayout, 1, 1);
w.setLayout(gLayout);
w.show();
return a.exec();
}
执行结果:
程序示例五:
#include <QApplication>
#include <QGridLayout>
#include <QVBoxLayout>
#include <QPushButton>
#include <QWidget>
#include <QObject>
#include <QLabel>
#include <QLineEdit>
#include <QCheckBox>
#include <QDebug>
int main(int argc, char **argv)
{
QApplication a(argc, argv);
QWidget w;
// 构建控件 头像、用户名、密码输入框等
QLabel *pImageLabel = new QLabel;
QLineEdit *pUserLineEdit = new QLineEdit;
QLineEdit *pPasswordLineEdit = new QLineEdit;
QCheckBox *pRememberCheckBox = new QCheckBox;
QCheckBox *pAutoLoginCheckBox = new QCheckBox;
QPushButton *pLoginButton = new QPushButton;
QPushButton *pRegisterButton = new QPushButton;
QPushButton *pForgotButton = new QPushButton;
pLoginButton->setFixedHeight(30);
pUserLineEdit->setFixedWidth(200);
// 设置头像
QPixmap pixmap("../image/b.png");
pImageLabel->setFixedSize(90, 90);
pImageLabel->setPixmap(pixmap);
pImageLabel->setScaledContents(true);
// 设置文本
pUserLineEdit->setPlaceholderText(QStringLiteral("QQ号码/手机/邮箱"));
pPasswordLineEdit->setPlaceholderText(QStringLiteral("密码"));
pPasswordLineEdit->setEchoMode(QLineEdit::Password);
pRememberCheckBox->setText(QStringLiteral("记住密码"));
pAutoLoginCheckBox->setText(QStringLiteral("自动登录"));
pLoginButton->setText(QStringLiteral("登录"));
pRegisterButton->setText(QStringLiteral("注册账号"));
pForgotButton->setText(QStringLiteral("找回密码"));
QGridLayout *pLayout = new QGridLayout();
// 头像 第0行,第0列开始,占3行1列
pLayout->addWidget(pImageLabel, 0, 0, 3, 1);
// 用户名输入框 第0行,第1列开始,占1行2列
pLayout->addWidget(pUserLineEdit, 0, 1, 1, 2);
pLayout->addWidget(pRegisterButton, 0, 4);
// 密码输入框 第1行,第1列开始,占1行2列
pLayout->addWidget(pPasswordLineEdit, 1, 1, 1, 2);
pLayout->addWidget(pForgotButton, 1, 4);
// 记住密码 第2行,第1列开始,占1行1列 水平居左 垂直居中
pLayout->addWidget(pRememberCheckBox, 2, 1, 1, 1, Qt::AlignLeft | Qt::AlignVCenter);
// 自动登录 第2行,第2列开始,占1行1列 水平居右 垂直居中
pLayout->addWidget(pAutoLoginCheckBox, 2, 2, 1, 1, Qt::AlignRight | Qt::AlignVCenter);
// 登录按钮 第3行,第1列开始,占1行2列
pLayout->addWidget(pLoginButton, 3, 1, 1, 2);
// 设置水平间距
pLayout->setHorizontalSpacing(10);
// 设置垂直间距
pLayout->setVerticalSpacing(10);
// 设置外间距
pLayout->setContentsMargins(10, 10, 10, 10);
w.setLayout(pLayout);
w.show();
return a.exec();
}
执行结果:
06. 附录
6.1 Qt教程汇总
网址:https://dengjin.blog.csdn.net/article/details/115174639