下面是一个表单布局,经典的表单布局分为2列
第一列是标题列,通常是QLabel,也可以是其他控件
第二列就是内容列,为具体的控件,也可以是个布局(比如水平布局,垂直布局...),布局里面套着多个控件
添加行
有多个重载形式
//参数1:标题列的文本
//参数2:内容列的控件
void QFormLayout::addRow(const QString &labelText, QWidget *field)
//参数1:标题列的控件
//参数2:内容列的控件
void QFormLayout::addRow(QWidget *label, QWidget *field)
//参数1:标题列的文本
//参数2:内容列是一个布局
void QFormLayout::addRow(const QString &labelText, QLayout *field)
比如下图,内容列是一个布局,布局里面有2个按钮
//参数1:一个控件或者布局
//没有指定标题列内容,添加的控件会充满整行
void QFormLayout::addRow(QWidget *widget)
void QFormLayout::addRow(QLayout *layout)
上面这种重载,没有指定标题列内容,添加的控件会充满整行,如下:
插入行
和添加行的重载差不多,需要多传一个参数,指定插在第几行
//在指定的row行插入
void QFormLayout::insertRow(int row, const QString &labelText, QWidget *field)
void QFormLayout::insertRow(int row, const QString &labelText, QLayout *field)
隐藏某一行
根据行号,隐藏这一行6.4版本开始支持
[since 6.4] void QFormLayout::setRowVisible(int row, bool on)
替换布局里面的某个Widget
[virtual] QLayoutItem *QLayout::replaceWidget(QWidget *from, QWidget *to, Qt::FindChildOptions options = Qt::FindChildrenRecursively)
替换之后要将原来的那个hide(),否在会堆叠在一起
设置行的换行策略
QFormLayout::RowWrapPolicy rowWrapPolicy() const
void setRowWrapPolicy(QFormLayout::RowWrapPolicy policy)
policy有三种取值
- QFormLayout::DontWrapRows,每一行左右排列,,默认就是这种
- QFormLayout::WrapLongRows,根据情况,比较长的行会被换行
- QFormLayout::WrapAllRows,每一行上下显示
获取行数
int QFormLayout::rowCount() const
根据行和列获取所在的item
QLayoutItem *QFormLayout::itemAt(int row, QFormLayout::ItemRole role) const
返回值:获取到的item,可以通过其widget()方法或者layout()方法获取item内部真实的项
参数1:row,行号
参数2:role,是一个枚举
有三种取值
- QFormLayout::LabelRole,指的是标题列
- QFormLayout::FieldRole,指的是内容列
- QFormLayout::SpanningRole,指的的是横跨2列的
比如itemAt(1,QFormLayout::FieldRole),表示获取第2行内容列的那一项
举例:
点击save按钮,遍历表单布局里的内容,校验表单布局里面的edit是否为空,为空则弹出错误提示,且将焦点移到为空的edit上
点击清除按钮,遍历表单布局里的内容,将edit的内容清空
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<QFormLayout>
#include<QPushButton>
#include<QLineEdit>
#include<QLabel>
#include<QHBoxLayout>
#include<QMessageBox>
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr): QWidget(parent)
{
resize(500,400);
QFormLayout* f_layout=new QFormLayout(this);
f_layout->setVerticalSpacing(10);
//添加一行
QLineEdit* name=new QLineEdit(this);
f_layout->addRow("名称",name);
QLineEdit* email=new QLineEdit(this);
f_layout->addRow("邮箱",email);
//插入一行
QLineEdit* age=new QLineEdit(this);
//插到第二行
f_layout->insertRow(1,"年龄",age);
//添加子布局
QPushButton* save=new QPushButton("save",this);
QPushButton* clr=new QPushButton("clear",this);
QHBoxLayout* h_box=new QHBoxLayout();
h_box->addWidget(save);
h_box->addWidget(clr);
f_layout->addRow(h_box);//不指定标题,则会充满整行
//绑定按钮的槽函数
//清除按钮:清空每一个输入框里的内容
connect(clr,&QPushButton::clicked,this,[=](){
//获取布局
QFormLayout* lay=(QFormLayout*)this->layout();
//遍历表单布局中的每一项
for(int i=0;i<lay->rowCount();++i)
{
//获取第i行指定列的元素,比如标题列、内容列、跨越了标题列和内容列
QLayoutItem* item=lay->itemAt(i,QFormLayout::FieldRole);
if(item==nullptr)//有可能为空,为什么可能为空,因为当前项有可能是其他的role
{
continue;
}
QLineEdit* e=(QLineEdit*)item->widget();
if(e==nullptr)//有可能为空,为什么可能为空,因为有可能是个布局
{
continue;
}
//获取真正的类型 是QLineEdit则清空
QString name=e->metaObject()->className();
if(name=="QLineEdit")
{
e->setText("");
}
}
});
connect(save,&QPushButton::clicked,this,[=](){
//获取布局
QFormLayout* lay=(QFormLayout*)this->layout();
QString err="";
//遍历表单布局中的每一项
for(int i=0;i<lay->rowCount();++i)
{
//获取标题,为了组装错误提示
QLayoutItem* title_item=lay->itemAt(i,QFormLayout::LabelRole);
if(title_item==nullptr)//有可能为空,为什么可能为空,因为当前项有可能是其他的role
{
continue;
}
QLabel* title_lbl=(QLabel*)title_item->widget();
if(title_lbl==nullptr)//有可能为空,为什么可能为空,因为有可能是个布局
{
continue;
}
QString title=title_lbl->text();
//获取第i行指定列的元素,比如标题列、内容列、跨越了标题列和内容列
QLayoutItem* item=lay->itemAt(i,QFormLayout::FieldRole);
if(item==nullptr)//有可能为空,为什么可能为空,因为当前项有可能是其他的role
{
continue;
}
//转为实际类型
QLineEdit* e=(QLineEdit*)item->widget();
if(e==nullptr)//有可能为空,为什么可能为空,因为有可能是个布局
{
continue;
}
QString name=e->metaObject()->className();
if(name=="QLineEdit")
{
//去掉内容里的空格后还是空的
if(e->text().trimmed()=="")
{
e->setFocus();
err+=title;
err+=" is empty!\n";
}
}
}
if(!err.isEmpty())
{
QMessageBox::information(this,"提示",err);
}
});
}
~Widget()=default;
};
#endif // WIDGET_H