QT之布局管理器(十九)

QT之布局管理器(十九)

        我们在之前的 GUI 开发中都是使用的是绝对定位,何谓绝对定位呢?就是我们直接在像素级指定各个组件的位置和大小。比如我们之前使用的 void QWidget::move(int x, int y);void QWidget::resize(int w, int h);这样存在的问题就是组件的位置和大小无法自适应父窗口的变化。

        我们先来看看绝对定位的代码和效果是怎样的?头文件代码如下:

#include <QWidget>
#include <QPushButton>

class Widget : public QWidget
{
    Q_OBJECT
private:
    QPushButton TestBtn1;
    QPushButton TestBtn2;
    QPushButton TestBtn3;
    QPushButton TestBtn4;

    void initControl();
public:
    Widget(QWidget *parent = 0);
    ~Widget();
};

        具体函数代码如下:

void Widget::initControl()
{
    TestBtn1.setText("Test Button 1");
    TestBtn1.move(20, 20);
    TestBtn1.resize(160, 30);

    TestBtn2.setText("Test Button 2");
    TestBtn2.move(20, 70);
    TestBtn2.resize(160, 30);

    TestBtn3.setText("Test Button 3");
    TestBtn3.move(20, 120);
    TestBtn3.resize(160, 30);

    TestBtn4.setText("Test Button 4");
    TestBtn4.move(20, 170);
    TestBtn4.resize(160, 30);
}

        图一为构建运行后得到的原始界面,图二为我们放大后的效果图:

QT之布局管理器(十九)                    QT之布局管理器(十九)

            图一                                                                                    图二

        那么有什么解决方法吗?答案就是布局管理器,它能够提供相关的类对界面组件进行布局管理。能够自动排列窗口中的界面组件,窗口变化后自动更新界面组件的大小。

        QLayout 是 Qt 中布局管理器的抽象基类,通过继承 QLayout 实现了功能各异且互补的布局管理器、Qt 中可以根据需要自定义布局管理器。注意:布局管理器不是界面部件,而是界面部件的定位策略!!!

        关系如下所示:

QT之布局管理器(十九)


           QBoxLayout 布局管理器 以水平或者垂直的方式管理界面组件,如下:

   QT之布局管理器(十九)QT之布局管理器(十九)

        我们下面来进行一组实验,我们先来以垂直的方式进行排布,代码如下:

void Widget::testVBoxLayout()
{
    QVBoxLayout* layout = new QVBoxLayout();

    TestBtn1.setText("Test Button 1");
    TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); // 设置水平和垂直方向都随之变化
    TestBtn1.setMinimumSize(160, 30);   // 设置最小界面大小

    TestBtn2.setText("Test Button 2");
    TestBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TestBtn2.setMinimumSize(160, 30);

    TestBtn3.setText("Test Button 3");
    TestBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TestBtn3.setMinimumSize(160, 30);

    TestBtn4.setText("Test Button 4");
    TestBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);;
    TestBtn4.setMinimumSize(160, 30);

    layout->setSpacing(20);         // 设置间距为20个像素
    layout->addWidget(&TestBtn1);   // 添加 TestBtn1
    layout->addWidget(&TestBtn2);
    layout->addWidget(&TestBtn3);
    layout->addWidget(&TestBtn4);

    setLayout(layout);
}

        图三为构建运行后得到的原始界面,图四为我们放大后的效果图:

QT之布局管理器(十九)                      QT之布局管理器(十九)

                图三                                                                                   图四

        我们再试下水平布局,在上面代码中仅仅只是将 QVBoxLayout 改成 QHBoxLayout,继续构建运行后效果如下:

QT之布局管理器(十九)

        那么我们的布局管理器还可以相互嵌套,形成更加复杂的布局方式。布局嵌套几乎可以完成所有常用的界面布局,我们还可以定义布局类以达到个性化布局的效果。下来我们就做个 QBoxLayout 嵌套示例,如下:

QT之布局管理器(十九)

        代码如下:

void Widget::testVHBoxLayout()
{
    QHBoxLayout* hLayout1 = new QHBoxLayout();  // 设置水平方向 hLayout1
    QHBoxLayout* hLayout2 = new QHBoxLayout();  // 设置水平方向 hLayout2
    QVBoxLayout* vLayout = new QVBoxLayout();   // 设置垂直方向 vLayout

    TestBtn1.setText("Test Button 1");
    TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TestBtn1.setMinimumSize(160, 30);

    TestBtn2.setText("Test Button 2");
    TestBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TestBtn2.setMinimumSize(160, 30);

    hLayout1->setSpacing(10);           // 设置间距
    hLayout1->addWidget(&TestBtn1);     // 水平方向添加 TestBtn1
    hLayout1->addWidget(&TestBtn2);     // 水平方向添加 TestBtn2

    TestBtn3.setText("Test Button 3");
    TestBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    TestBtn3.setMinimumSize(160, 30);

    TestBtn4.setText("Test Button 4");
    TestBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);;
    TestBtn4.setMinimumSize(160, 30);

    hLayout2->setSpacing(10);
    hLayout2->addWidget(&TestBtn3);
    hLayout2->addWidget(&TestBtn4);

    vLayout->setSpacing(10);            // 设置间距
    vLayout->addLayout(hLayout1);       // 竖直方向添加 hLayout1
    vLayout->addLayout(hLayout2);       // 竖直方向添加 hLayout2

    setLayout(vLayout);
}

        构建运行效果如下:

QT之布局管理器(十九)

        那么本次我们学习了布局管理相关的知识。绝对定位的布局方式是无法适应窗口的变化的,在 Qt 中提供了相关的类对界面组件进行布局管理。Qt 预定义了功能各异的且互补的布局管理器,布局管理器能够相互嵌套形成复杂的布局。在后面我们会接着对 Qt 的布局管理方式进行学习。