QFormLayout顧名思義,主要用來做表單的輸入及顯示。和前面講到的QBoxLayout、QGridLayout類似,QFormLayout可以插入widget、layout,直接用QGridLayout也可以做出QFormLayout的效果。
下面開始介紹QFormLayout用作表單應用時相關的接口函數。
基本方法
在末尾新增
左側添加標籤,右側添加widget或layout
void addRow(QWidget *label, QWidget *field)
void addRow(QWidget *label, QLayout *field)
一般,左側添加一個QLabel用來顯示文本信息,右側增加一個QLineEdit用來給用戶輸入。
左側使用QFormLayout自帶標籤,右側增加widget或layout
void addRow(const QString &labelText, QWidget *field)
void addRow(const QString &labelText, QLayout *field)
針對上面提到的接口函數,QFormLayout提供了一種更爲便利的方法,該方法直接使用QFormLayout內部的QLabel,labelText所傳參數爲左側label所顯示的內容。
跨越兩列增加widget或layout
void addRow(QWidget *widget)
void addRow(QLayout *layout)
該方法直接在末尾添加一個橫跨兩列的widget或layout,比如在末尾添加一個含有ok和clear按鈕的layout。
在指定位置新增
void insertRow(int row, QWidget *label, QWidget *field)
void insertRow(int row, QWidget *label, QLayout *field)
void insertRow(int row, const QString &labelText, QWidget *field)
void insertRow(int row, const QString &labelText, QLayout *field)
void insertRow(int row, QWidget *widget)
void insertRow(int row, QLayout *layout)
只不過加了一個行號,其他含義和用法和上面一樣,這裏就不分條介紹了。
刪除
刪除某一行
void removeRow(int row)
刪除某一widget或layout
void removeRow(QWidget *widget)
void removeRow(QLayout *layout)
獲取
QLayoutItem *itemAt(int row, QFormLayout::ItemRole role) const
返回具有指定角色(列)的給定行中的佈局項。如果沒有這樣的項,則返回nullptr。
QFormLayout::ItemRole參數列表:
QFormLayout::LabelRole A label widget.
QFormLayout::FieldRole A field widget.
QFormLayout::SpanningRole A widget that spans label and field columns.
這裏其實和前面add或insert時對應的label或field對應。
演示表單提交的代碼
界面編寫:
自定義Widget類的構造函數代碼
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
//創建表單佈局
QFormLayout *flay = new QFormLayout();
//創建QLabel作爲表單標題顯示
QLabel *title = new QLabel("學生信息錄入");
//居中顯示
title->setAlignment(Qt::AlignHCenter);
//設置字體大小
title->setStyleSheet("font-size:20px");
//放置標題到最前面
flay->addRow(title);
QLineEdit *nameLineEdit = new QLineEdit();
//添加name
flay->addRow("&Name:", nameLineEdit);
//添加email
QLineEdit *emailLineEdit = new QLineEdit();
flay->addRow("&Email:", emailLineEdit);
//添加age
QSpinBox *ageSpinBox = new QSpinBox();
flay->addRow("&Age:", ageSpinBox);
//在最底部增加兩個按鈕
QHBoxLayout *hlay = new QHBoxLayout();
QPushButton *btOk = new QPushButton("ok");
QPushButton *btClear = new QPushButton("clear");
hlay->addWidget(btOk);
hlay->addWidget(btClear);
flay->addRow(hlay);
//設置widget的主佈局
this->setLayout(flay);
}
main函數代碼
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
運行效果:
其中"&Age:"、"&Email:"、"&Name:",前面都有加一個'&'符號,其目的是可以用快捷鍵"ALT+首字母"將光標切換到目標行進行輸入。
表單的提交
所謂表單的提交就是在用戶按下ok按鈕時,拿到用戶輸入的各項數據,並作出相應的處理。
既然和按鈕按下有關,那就要先綁定按鈕按下事件。
在widget構造函數中新增以下代碼,用於信號與槽的綁定
connect(btOk,SIGNAL(clicked()),this,SLOT(OnOkBtClicked()));
槽函數的具體實現
void Widget::OnOkBtClicked()
{
//得到QFormLayout指針
QFormLayout *flay = static_cast<QFormLayout *>(this->layout());
if(!flay)
{
qDebug() << "Get layout failed!";
return;
}
//用來收集錯誤信息
QString errCode = "";
//用來收集正確的信息
QString inputMessage = "";
//遍歷所有行,逐個取出所需內容
for(int i = 0 ; i < flay->rowCount() ; i++)
{
//獲取label
QLayoutItem *itemLab = flay->itemAt(i, QFormLayout::LabelRole);
if(!itemLab)
continue;
QLabel *lab = static_cast<QLabel*>(itemLab->widget());
if(!lab)
continue;
//獲取內容輸入框
QLayoutItem *item = flay->itemAt(i, QFormLayout::FieldRole);
if(!item)
continue;
//獲取widget
QWidget *widget = item->widget();
if(!widget)
continue;
//取到label的文字
QString labelText = lab->text();
//去掉前面的'&'
if(labelText[0] == '&')
labelText.remove(0,1);
//widget類型爲QLineEdit
if(QString(widget->metaObject()->className()) == "QLineEdit")
{
//強制轉換
QLineEdit *edit = static_cast<QLineEdit*>(widget);
if(!edit)
continue;
//如果是空的,證明此項沒有輸入,增加錯誤信息
if(edit->text().isEmpty())
{
errCode += labelText + "null\n";
continue;
}
//放到正確信息裏
inputMessage += labelText + edit->text() + "\n";
}
else if(QString(widget->metaObject()->className()) == "QSpinBox")
{
QSpinBox *spinbox = static_cast<QSpinBox*>(widget);
if(!spinbox)
continue;
if(spinbox->text().isEmpty())
{
errCode += labelText + "null\n";
continue;
}
inputMessage += labelText + spinbox->text() + "\n";
}
else {
continue;
}
}
//彈出MessageBox提示成功或失敗
if(!errCode.isEmpty())
QMessageBox::warning(this,"Input Error",errCode);
else {
QMessageBox::information(this,"Input OK",inputMessage);
}
}
整個代碼的功能是逐行獲取用戶輸入,如果發現輸入爲空時,彈出警告窗口,提醒用戶哪些項爲空。如果程序成功獲取到用戶輸入的所有內容時,彈出information窗口,顯示出用戶的輸入。
其中的關鍵點是itemAt的使用,當想要獲取左側label時,需要給它的第二個參數傳遞QFormLayout::LabelRole。當想要獲取右側的用戶輸入時,需要給它的第二個參數傳遞QFormLayout::FieldRole。除此之外,還要做類型的強轉、空指針的判斷、widget對應的ClassName的獲取,這些缺一不可。本程序中沒有用到任何全局可訪問的變量,全部通過動態獲取的方式獲取目標指針。
程序運行結果:
正確輸入
有空項時: