在上篇文章中描述了实中套虚(用setLayout),虚中套实(用addWidget)。
本文再加1条,虚中套虚(用addLayout)。
所谓虚中套虚,是layout 套 layout 。
另外用循环代码生成从左到右的相同结构界面。这是和拖拉GUI组件相比的优点之一。

图1-效果

图2-1 布局关系图1
说明:按照实中套虚,虚中套实原则

图2-1布局关系示意图2
说明:因为可以虚中套虚,省掉了图2-1中紫色部分
1.头文件
#ifndef WIDGET_H
 #define WIDGET_H
#include <QWidget>
 #include <QLabel>
 #include <QString>
 #include <QLineEdit>
 //#include <QHBoxLayout>
 #include <QGridLayout>
 #include <QFrame>
 QT_BEGIN_NAMESPACE
 namespace Ui {
 class Widget;
 }
 QT_END_NAMESPACE
 //定义了两个结构体,实现界面和数据分离
struct UserData//数据
 {
     QString str;
 };
struct UserPlot//界面显示组件,结构化后方便调整界面
 {
     QWidget w;//外观上包含下面三个,实际上经过布局中继
     QLabel lb;
     QLineEdit le;
     QFrame *l;//分割线
 };
 class Widget : public QWidget
 {
     Q_OBJECT
 public:
     Widget(QWidget *parent = nullptr);
     ~Widget();
 private:
     Ui::Widget *ui;
     UserPlot up[3];//3个左到右排列
     UserData data[3];//3个,0对应上面的0,1对应上面的1,2对应上面的2
 };
 #endif // WIDGET_H
  
2.cpp文件
#include "widget.h"
 #include "ui_widget.h"
Widget::Widget(QWidget *parent)
     : QWidget(parent)
     , ui(new Ui::Widget)
 {
     ui->setupUi(this);
     QHBoxLayout *mainLayout = new QHBoxLayout;
     QGridLayout *subLayout0 = new QGridLayout;
     QGridLayout *subLayout1 = new QGridLayout;
     QGridLayout *subLayout2 = new QGridLayout;
     QGridLayout *subLayoutArray[3]= {subLayout0,subLayout1,subLayout2};
     QFrame *fp;
     data[0].str=QString("BeiJin");
     data[1].str=QString("ChongQin");
     data[2].str=QString("GuangZhou");
     for(int i=0;i<3;i++)//mainLayout布局里套了3个QWidget或layout
     {
         up[i].lb.setText(data[i].str);
         if (i<2)
         {   up[i].l=new QFrame(this);
             fp=up[i].l;//竖线
             fp->setFrameShape(QFrame::VLine);//竖线
             fp->setFrameShadow(QFrame::Sunken);//竖线
         }
         subLayoutArray[i]->addWidget(&up[i].lb,0,0,1,1,Qt::AlignTop);//每个QGridLayout里
                                                                                                         //套了QLabel
         subLayoutArray[i]->addWidget(&up[i].le,1,0,1,1,Qt::AlignTop);//每个QGridLayout里
                                                                                                         //套了QLineEdit
         if (i<2)
         subLayoutArray[i]->addWidget(fp,0,1,2,1);//每个QGridLayout里套了QFrame,
                                                                          //实际上是分割竖线
         //up[i].w.setLayout(subLayoutArray[i]);//每个QWidget里套了个QGridLayout
        //mainLayout->addWidget(&up[i].w);//上面一行与本行的效果,等效于下一行
        mainLayout->addLayout(subLayoutArray[i]);//layout 里 套 layout
         this->resize(400,100);
     }
     setLayout(mainLayout);//widget里套了个mainLayout布局
 }
Widget::~Widget()
 {
     delete ui;
 }