Qt 水平布局 QHBoxLayout

Qt 像其他编辑器一样,在添加控件时,也可以自定义控件的坐标,让每个控件处于你希望的位置,但是这样相对麻烦,而 Qt 提供了一系列布局功能,本文介绍的就是水平布局 QHBoxLayout,他可以将一系列控件加入其布局中,然后将整个布局应用到窗口中。详见代码:

【代码实现】

注意:我们使用的都是自己继承的 QWidget 类来创建一个窗口,如果不清楚这个窗口是如何创建的,请参考“使用 Qt 构建一个简单的窗体程序”。

#ifndef CWIDGETS_H
#define CWIDGETS_H

#include <QWidget>
#include <QHBoxLayout>
#include <QPushButton>

class CWidgets : public QWidget
{
    Q_OBJECT
public:
    explicit CWidgets(QWidget *parent = 0);

    // 水平布局框架
    QHBoxLayout* _layout;

    // 按钮
    QPushButton* _button1;
    QPushButton* _button2;
    QPushButton* _button3;

signals:

public slots:
};

#endif // CWIDGETS_H
#include "cwidgets.h"

CWidgets::CWidgets(QWidget *parent) : QWidget(parent)
{
    // 将成员变量 _layout new 出来
    _layout = new QHBoxLayout;

    // 将三个按钮也 new 出来并命名
    _button1 = new QPushButton("button1");
    _button2 = new QPushButton("button2");
    _button3 = new QPushButton("button3");

    // 将三个按钮添加到 _layout 布局中
    _layout->addWidget(_button1);
    _layout->addWidget(_button2);
    _layout->addWidget(_button3);

    // 调用 CWidget 成员函数 setLayout 将我们新建的布局应用到窗体中
    setLayout(_layout);
}
#include <QApplication>
#include "cwidgets.h"

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    CWidgets w;
    w.show();

    return app.exec();
}

通过以上代码,我们的窗口创建完成后就是下图的状态了:

2015-06-17_102543

当你拉伸窗口时,按钮也回跟随窗口变化,如下图:

2015-06-17_102742

如果你不希望拉伸窗口时控件跟随着变长,那么你可以调用 addStretch() 函数,增加一个“弹簧”,如下代码所示:

    // 在布局中添加一个弹簧,让控件不会跟随窗口变大而变大
    _layout->addStretch(1);

添加 addStretch 后,再拉伸窗体,按钮就不会跟着窗体拉长了:

2015-06-17_104140

那这个 addStretch() 函数到底是做什么用的?他是如何起到这样的作用的?

其实我们每个添加的控件都是可以设定在窗口中的比例的,如果你不指定窗口比例,那么就以控件默认的大小来显示,这个 addStretch() 函数相当于在水平布局中,增加了一个比例为 1 的控件,只不过这个控件是什么都不显示的,其他控件因为没有指定比例,所以保持原有大小不变,而一拉伸窗口,用 addStretch() 添加的“控件”就会跟随窗口变大而变大,给我们的错觉就是像一个弹簧一样,把三个没有指定大小的控件一直挤在左侧。

如果我们设定了控件的比例会怎么样呢?如下代码:

// 将三个按钮添加到 _layout 布局中
_layout->addWidget(_button1, 1);    // 占整个窗口的 1/n
_layout->addWidget(_button2, 2);    // 占整个窗口的 2/n
_layout->addWidget(_button3, 3);    // 占整个窗口的 3/n

// 在布局中添加一个弹簧,让控件不会跟随窗口变大而变大
_layout->addStretch(1);             // 占整个窗口的 1/n

我们在 addwidget() 函数中增加了第二个参数,设定了控件的比例,如注释所写,按钮 1 占用了 1/n 的比例,按钮 2 占用了 2/n 的比例,按钮 3 占用了 3/n 的比例,最后一个插入的“弹簧”占用了 1/n 的比例,此时相当于在一个水平布局中 n = 7,那按钮 1 就是占用 1/7 的比例,按钮 2 占用了 2/7 的比例,依次类推,效果就是下图这样了:

2015-06-17_105424

【在其他控件中间插入控件】

以上是比例相关的解释,下面我们来看一下如何在这些按钮中插入一个按钮。比如我希望将一个按钮 button4 插入到 button1 和 button2 中间,那么你可以通过 insertWidget() 函数来实现:

// 在控件 0 后面插入一个控件,这个控件被插入后就是在位置 1
_layout->insertWidget(1, new QPushButton("button4"));

2015-06-17_110058

【在控件之间增加一个间隔】

如果你希望两个控件之间能有一部分间隔,你可以通过 addSpacing() 函数来实现:

// button1 后面增加一个间隔,长度为50
_layout->addSpacing(50);

2015-06-17_110322

【设置 QHBoxLayout 的边距】

上面所有图中我们都可以看出,窗口和控件之间是有一点点距离的,这个距离我们也可以自己来控制,那就是调用 setMargin() 函数来实现:

// 设置 QHBoxLayout 边距为 0
_layout->setMargin(0);

2015-06-17_110610

【设置全局控件之间的距离】

如果你希望将所有控件之间的距离都控制在一个长度,那么你可以通过 setSpacing() 函数来实现,它不同与 addSpcing() 函数,setSpacing() 函数是设置所有控件之间的间距:

// 设置所有控件之间的间距为 0
_layout->setSpacing(0);

2015-06-17_110743

与上图相比,可以看出控件之间的间距没有了。

【总结】

最后我们来将所有功能重新梳理一下成为如下代码:

#include "cwidgets.h"

CWidgets::CWidgets(QWidget *parent) : QWidget(parent)
{
    // 将成员变量 _layout new 出来并设置父窗口,无需后面再调用setLayout()函数
    _layout = new QHBoxLayout(this);
    // 设置 QHBoxLayout 边距为 0
    _layout->setMargin(0);
    // 设置所有控件之间的间距为 0
    _layout->setSpacing(0);

    // 添加控件的同时直接在参数中将控件 new 出来,这样代码可以更简洁
    _layout->addWidget(_button1 = new QPushButton("button1"), 1);
    // 添加间距
    _layout->addSpacing(50);
    _layout->addWidget(_button2 = new QPushButton("button2"), 2);
    _layout->addWidget(_button3 = new QPushButton("button3"), 3);

    // 在布局中添加一个弹簧,让控件不会跟随窗口变大而变大
    _layout->addStretch(1);             // 占整个窗口的 1/n

    // 在控件 0 后面插入一个控件,这个控件被插入后就是在位置 1
    _layout->insertWidget(1, new QPushButton("button4"));
}

 

说说你的想法