【QT】布局管理器

07-16 1091阅读

布局管理器

  • 布局管理器
    • 1. 垂直布局
    • 2. 水平布局
    • 3. 网格布局
    • 4. 表单布局
    • 5. Spacer

      布局管理器

      之前使⽤ Qt 在界⾯上创建的控件, 都是通过 “绝对定位” 的⽅式来设定的;也就是每个控件所在的位置, 都需要计算坐标, 最终通过 setGeometry 或者 move ⽅式摆放过去。

      这种设定⽅式其实并不⽅便. 尤其是界⾯如果内容⽐较多, 不好计算. ⽽且⼀个窗⼝⼤⼩往往是可以调整的, 按照绝对定位的⽅式, 也⽆法⾃适应窗⼝⼤⼩。因此 Qt 引⼊ “布局管理器” (Layout) 机制, 来解决上述问题。

      1. 垂直布局

      使⽤ QVBoxLayout 表示垂直的布局管理器。V 是 vertical 的缩写。

      核心属性:

      【QT】布局管理器

      Layout 只是⽤于界⾯布局, 并没有提供信号。

      代码示例:使用 QVBoxLayout 管理多个控件.

      1)编写代码, 创建布局管理器和三个按钮. 并且把按钮添加到布局管理器中.

      • 使⽤ addWidget 把控件添加到布局管理器中.

      • 使⽤ setLayout 设置该布局管理器到 widget 中.

          		Widget::Widget(QWidget *parent)
          		    : QWidget(parent)
          		    , ui(new Ui::Widget)
          		{
          		    ui->setupUi(this);
          		
          		    // 创建三个按钮
          		    QPushButton* button1 = new QPushButton("按钮1");
          		    QPushButton* button2 = new QPushButton("按钮2");
          		    QPushButton* button3 = new QPushButton("按钮3");
          		
          		    // 创建布局管理器,并且把按钮添加进去
          		    // 如果创建的时候指定父元素为 this,则后面不需要 setLayout 方法了
          		    QVBoxLayout* layout = new QVBoxLayout();
          		    layout->addWidget(button1);
          		    layout->addWidget(button2);
          		    layout->addWidget(button3);
          		
          		    // 把布局管理器设置到 widget 中
          		    this->setLayout(layout);
          		}
        

        通过上述代码的⽅式, 只能给这个 widget 设定⼀个布局管理器. 实际上也可以通过 Qt Design 在⼀个窗⼝中创建多个布局管理器。

        代码示例2:创建两个 QVBoxLayout

        1)在界⾯上创建两个 QVBoxLayout , 每个 QVBoxLayout 各放三个按钮.

        点击如下红框创建 QVBoxLayout:

        【QT】布局管理器

        2)运⾏程序, 可以看到这些按钮已经⾃动排列好. 只不过当前这些按钮的位置不能随着窗⼝⼤⼩⾃动变化.

        2. 水平布局

        使⽤ QHBoxLayout 表⽰垂直的布局管理器. H 是 horizontal 的缩写.

        核心属性 (和 QVBoxLayout 属性是⼀致的):

        【QT】布局管理器

        代码示例:使用 QHBoxLayout 管理控件

        1)编写代码, 创建布局管理器和三个按钮. 并且把按钮添加到布局管理器中.

        			Widget::Widget(QWidget *parent)
        			    : QWidget(parent)
        			    , ui(new Ui::Widget)
        			{
        			    ui->setupUi(this);
        			
        			    // 创建三个按钮
        			    QPushButton* button1 = new QPushButton("按钮1");
        			    QPushButton* button2 = new QPushButton("按钮2");
        			    QPushButton* button3 = new QPushButton("按钮3");
        			
        			    // 创建水平布局管理器
        			    QHBoxLayout* layout = new QHBoxLayout();
        			    layout->addWidget(button1);
        			    layout->addWidget(button2);
        			    layout->addWidget(button3);
        			
        			    // 设置 layout 到 widget 上
        			    this->setLayout(layout);
        			}
        

        代码示例2:嵌套的 layout

        1)在代码中创建以下内容

        使⽤ addLayout 给 layout 中添加⼦ layout.

        			Widget::Widget(QWidget *parent)
        			    : QWidget(parent)
        			    , ui(new Ui::Widget)
        			{
        			    ui->setupUi(this);
        			
        			    // 创建顶层 layout
        			    QVBoxLayout* layoutParent = new QVBoxLayout();
        			    this->setLayout(layoutParent);
        			
        			    // 添加两个按钮进去
        			    QPushButton* button1 = new QPushButton("按钮1");
        			    QPushButton* button2 = new QPushButton("按钮2");
        			    layoutParent->addWidget(button1);
        			    layoutParent->addWidget(button2);
        			
        			    // 创建子 layout
        			    QHBoxLayout* layoutChild = new QHBoxLayout();
        			
        			    // 添加两个按钮进去
        			    QPushButton* button3 = new QPushButton("按钮3");
        			    QPushButton* button4 = new QPushButton("按钮4");
        			    layoutChild->addWidget(button3);
        			    layoutChild->addWidget(button4);
        			
        			    // 把子 layout 添加到父 layout 中
        			    layoutParent->addLayout(layoutChild);
        			}
        

        【QT】布局管理器

        3. 网格布局

        Qt 中还提供了 QGridLayout ⽤来实现⽹格布局的效果. 可以达到 M * N 的这种⽹格的效果.

        核心属性:

        整体和 QVBoxLayout 以及 QHBoxLayout 相似. 但是设置 spacing 的时候是按照垂直⽔平两个⽅向来设置的.

        【QT】布局管理器

        代码示例:使⽤ QGridLayout 管理元素

        1)代码中创建 QGridLayout 和 4 个按钮.

        使⽤ addWidget 添加控件到布局管理器中. 但是添加的同时会指定两个坐标. 表⽰放在第⼏⾏, 第⼏列.

        			Widget::Widget(QWidget *parent)
        			    : QWidget(parent)
        			    , ui(new Ui::Widget)
        			{
        			    ui->setupUi(this);
        			    // 创建 4 个按钮
        			    QPushButton* button1 = new QPushButton("按钮1");
        			    QPushButton* button2 = new QPushButton("按钮2");
        			    QPushButton* button3 = new QPushButton("按钮3");
        			    QPushButton* button4 = new QPushButton("按钮4");
        			
        			    // 创建网格布局管理器,并且添加元素
        			    QGridLayout* layout = new QGridLayout();
        			    layout->addWidget(button1, 0, 0);
        			    layout->addWidget(button2, 0, 1);
        			    layout->addWidget(button3, 1, 0);
        			    layout->addWidget(button4, 1, 1);
        			
        			    // 设置 layout 到窗口中
        			    this->setLayout(layout);
        			}
        
        1. 执⾏代码, 观察效果. 可以看到当前的这⼏个按钮是按照 2 ⾏ 2 列的⽅式排列的.

        【QT】布局管理器

        代码示例: 设置 QGridLayout 中元素的大小比例

        1)创建 6 个按钮, 按照 2 ⾏ 3 列的⽅式排列

        • 使用 setColumnStretch 设置每⼀列的拉伸系数

            		Widget::Widget(QWidget *parent)
            		    : QWidget(parent)
            		    , ui(new Ui::Widget)
            		{
            		    ui->setupUi(this);
            		
            		    QPushButton* button1 = new QPushButton("按钮1");
            		    QPushButton* button2 = new QPushButton("按钮2");
            		    QPushButton* button3 = new QPushButton("按钮3");
            		    QPushButton* button4 = new QPushButton("按钮4");
            		    QPushButton* button5 = new QPushButton("按钮5");
            		    QPushButton* button6 = new QPushButton("按钮6");
            		
            		    // 创建网格布局管理器,并且添加元素
            		    QGridLayout* layout = new QGridLayout();
            		    layout->addWidget(button1, 0, 0);
            		    layout->addWidget(button2, 0, 1);
            		    layout->addWidget(button3, 0, 2);
            		    layout->addWidget(button4, 1, 0);
            		    layout->addWidget(button5, 1, 1);
            		    layout->addWidget(button6, 1, 2);
            		
            		    // 设置拉伸比例
            		    // 第 0 列拉伸比例设为 1
            		    layout->setColumnStretch(0, 1);
            		    // 第 1 列拉伸比例设为 0,即为固定大小,不参与拉伸
            		    layout->setColumnStretch(1, 0);
            		    // 第 2 列拉伸比例设为 3,即为第 2 列的宽度是第 0 列的 3 倍
            		    layout->setColumnStretch(2, 3);
            		
            		    // 设置 layout 到窗口中
            		    this->setLayout(layout);
            		}
          

          代码示例2:设置垂直⽅向的拉伸系数

          1)编写代码, 创建 6 个按钮, 按照 3 ⾏ 2 列⽅式排列.

          使⽤ setSizePolicy 设置按钮的尺⼨策略. 可选的值如下:

          • QSizePolicy::Ignored : 忽略控件的尺⼨,不对布局产⽣影响

          • QSizePolicy::Minimum : 控件的最⼩尺⼨为固定值,布局时不会超过该值。

          • QSizePolicy::Maximum : 控件的最⼤尺⼨为固定值,布局时不会⼩于该值。

          • QSizePolicy::Preferred : 控件的理想尺⼨为固定值,布局时会尽量接近该值。

          • QSizePolicy::Expanding : 控件的尺⼨可以根据空间调整,尽可能占据更多空间。

          • QSizePolicy::Shrinking : 控件的尺⼨可以根据空间调整,尽可能缩⼩以适应空间。

              		Widget::Widget(QWidget *parent)
              		    : QWidget(parent)
              		    , ui(new Ui::Widget)
              		{
              		    ui->setupUi(this);
              		
              		    QPushButton* button1 = new QPushButton("按钮1");
              		    QPushButton* button2 = new QPushButton("按钮2");
              		    QPushButton* button3 = new QPushButton("按钮3");
              		    QPushButton* button4 = new QPushButton("按钮4");
              		    QPushButton* button5 = new QPushButton("按钮5");
              		    QPushButton* button6 = new QPushButton("按钮6");
              		
              		    // 设置按钮的 sizePolicy,此时按钮的水平方向和垂直方向都会尽量舒展开
              		    button1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
              		    button2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
              		    button3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
              		    button4->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
              		    button5->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
              		    button6->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
              		
              		    // 创建网格布局管理器,并添加元素
              		    QGridLayout* layout = new QGridLayout();
              		    layout->addWidget(button1, 0, 0);
              		    layout->addWidget(button2, 0, 1);
              		    layout->addWidget(button3, 1, 0);
              		    layout->addWidget(button4, 1, 1);
              		    layout->addWidget(button5, 2, 0);
              		    layout->addWidget(button6, 2, 1);
              		
              		    // 设置拉伸比例
              		    // 第 0 行拉伸比例设为 1
              		    layout->setRowStretch(0, 1);
              		    // 第 1 行拉伸比例设为 0,即为固定大小,不参与拉伸
              		    layout->setRowStretch(1, 0);
              		    // 第 2 行拉伸比例设为 3,即为第 2 行的宽度是第 0 行的 3 倍
              		    layout->setRowStretch(2, 3);
              		
              		    // 设置 layout 到窗口中
              		    this->setLayout(layout);
              		}
            

            2)执⾏代码, 观察效果.

            此时的按钮垂直⽅向都舒展开了. 并且调整窗⼝尺⼨, 也会按照设定的⽐例同步变化.

            【QT】布局管理器

            总的来说, 使⽤ QGridLayout 能够代替很多 QHBoxLayout 和 QVBoxLayout 嵌套的场景. 毕竟嵌套的代码写起来是⽐较麻烦的。

            另外不要忘了, QGridLayout ⾥⾯也能嵌套 QHBoxLayout 和 QVBoxLayout ,QHBoxLayout 和 QVBoxLayout ⾥⾯也能嵌套 QGridLayout;灵活使⽤上述布局管理器, 就可以实现出任意的复杂界⾯。

            4. 表单布局

            除了上述的布局管理器之外, Qt 还提供了 QFormLayout , 属于是 QGridLayout 的特殊情况, 专⻔⽤于实现两列表单的布局.

            这种表单布局多⽤于让⽤⼾填写信息的场景. 左侧列为提⽰, 右侧列为输⼊框.

            代码示例:使⽤ QFormLayout 创建表单.

            1)编写代码, 创建 QFormLayout , 以及三个 label 和三个 lineEdit

            • 使⽤ addRow ⽅法来添加⼀⾏. 每⾏包含两个控件. 第⼀个控件固定是 QLabel / ⽂本, 第⼆个控件则可以是任意控件.

            • 如果把第⼀个参数填写为 NULL, 则什么都不显⽰.

                		Widget::Widget(QWidget *parent)
                		    : QWidget(parent)
                		    , ui(new Ui::Widget)
                		{
                		    ui->setupUi(this);
                		
                		    // 创建 layout
                		    QFormLayout* layout = new QFormLayout();
                		    this->setLayout(layout);
                		
                		    // 创建三个 label
                		    QLabel* label1 = new QLabel("姓名");
                		    QLabel* label2 = new QLabel("年龄");
                		    QLabel* label3 = new QLabel("电话");
                		
                		    // 创建三个 lineEdit
                		    QLineEdit* lineEdit1 = new QLineEdit();
                		    QLineEdit* lineEdit2 = new QLineEdit();
                		    QLineEdit* lineEdit3 = new QLineEdit();
                		
                		    // 创建一个提交按钮
                		    QPushButton* button = new QPushButton("提交");
                		
                		    // 把上述元素添加到 layout 中
                		    layout->addRow(label1, lineEdit1);
                		    layout->addRow(label2, lineEdit2);
                		    layout->addRow(label3, lineEdit3);
                		    layout->addRow(NULL, button);
                		}
              

              5. Spacer

              使用布局管理器的时候, 可能需要在控件之间, 添加⼀段空白. 就可以使用 QSpacerItem 来表示.

              核心属性:

              【QT】布局管理器

              上述属性在构造函数设置即可.

              代码示例:创建⼀组左右排列的按钮.

              1)在界⾯上创建⼀个 QVBoxLayout , 并添加两个按钮.

              			Widget::Widget(QWidget *parent)
              			    : QWidget(parent)
              			    , ui(new Ui::Widget)
              			{
              			    ui->setupUi(this);
              			
              			    QHBoxLayout* layout = new QHBoxLayout();
              			    this->setLayout(layout);
              			
              			    QPushButton* button1 = new QPushButton("按钮1");
              			    QPushButton* button2 = new QPushButton("按钮2");
              			
              			    layout->addWidget(button1);
              			    layout->addWidget(button2);
              			}
              

              2)直接运⾏程序, 可以看到两个按钮是紧挨着的

              【QT】布局管理器

              3)在两个按钮中间添加⼀个 spacer

              			Widget::Widget(QWidget *parent)
              			    : QWidget(parent)
              			    , ui(new Ui::Widget)
              			{
              			    ui->setupUi(this);
              			
              			    QHBoxLayout* layout = new QHBoxLayout();
              			    this->setLayout(layout);
              			
              			    QPushButton* button1 = new QPushButton("按钮1");
              			    QPushButton* button2 = new QPushButton("按钮2");
              			
              			    // 创建 Spacer
              			    QSpacerItem* spacer = new QSpacerItem(200, 20);
              			
              			    layout->addWidget(button1);
              			
              			    // 在两个 widget 中间添加空白
              			    layout->addSpacerItem(spacer);
              			
              			    layout->addWidget(button2);
              			}
              

              4)运⾏程序, 观察代码效果. 可以看到两个按钮之间已经存在了间隔了.

              调整 QSpacerItem 不同的尺⼨, 即可看到不同的间距。

              【QT】布局管理器

              在 Qt Designer 中, 也可以直接给界⾯上添加 spacer:

              【QT】布局管理器

VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]