Qt佈局管理器之表單佈局(QFormLayout)

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的獲取,這些缺一不可。本程序中沒有用到任何全局可訪問的變量,全部通過動態獲取的方式獲取目標指針。

程序運行結果:

正確輸入

有空項時:

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章