北屋教程网

专注编程知识分享,从入门到精通的编程学习平台

Qt5 C++入门教程-第8章 布局管理(qt常用的布局有哪些)

大道至简,在 Qt5 C++入门教程的这一部分,,我们将讨论窗口部件(widget)的布局管理。我们会提到 QHBoxLayout(水平布局管理器)、QVBoxLayout(垂直布局管理器)、QFormLayout(表单布局管理器)和 QGridLayout(网格布局管理器)。

一个典型的应用程序由各种窗口部件组成。这些窗口部件被放置在布局中。程序员必须管理应用程序的布局。在 Qt5 中,我们有两种选择:

  1. 绝对定位
  2. 布局管理器
  • 绝对定位
    程序员以像素为单位指定每个窗口部件的位置和大小。当我们使用绝对定位时,必须了解以下几点:
  1. 当我们调整窗口大小时,窗口部件的大小和位置不会改变。
  2. 应用程序在不同平台上的显示效果可能不同(通常效果不佳)。
  3. 在应用程序中更改字体可能会破坏布局。
  4. 如果我们决定更改布局,必须完全重新设计布局,这既繁琐又耗时。

可能存在一些情况适合使用绝对定位。但在大多数实际应用程序中,程序员会使用布局管理器。

  • absolute.cpp
#include <QApplication>
#include <QDesktopWidget>
#include <QTextEdit>

class Absolute : public QWidget {
public:
    Absolute(QWidget *parent = nullptr);
};

Absolute::Absolute(QWidget *parent)
    : QWidget(parent) {
    auto *ledit = new QTextEdit(this);
    ledit->setGeometry(5, 5, 200, 150);
}

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    Absolute window;
    window.setWindowTitle("Absolute");
    window.show();
    return app.exec();
}

setGeometry 方法用于以绝对坐标的方式在窗口上定位窗口部件。

auto *edit = new QTextEdit(this);
ledit->setGeometry(5, 5, 200, 150);

我们创建了一个 QTextEdit 窗口部件,并手动对其进行定位。setGeometry 方法有两个作用:它将窗口部件定位到绝对坐标,并调整窗口部件的大小。


  • Qt5 QVBoxLayout
    QVBoxLayout 类将窗口部件垂直排列。使用 addWidget 方法将窗口部件添加到布局中。
  • vertical_box.h
#pragma once
#include <QWidget>

class VerticalBox : public QWidget {
public:
    VerticalBox(QWidget *parent = nullptr);
};
  • vertical_box.cpp
#include <QVBoxLayout>
#include <QPushButton>
#include "vertical_box.h"

VerticalBox::VerticalBox(QWidget *parent)
    : QWidget(parent) {
    auto *vbox = new QVBoxLayout(this);
    vbox->setSpacing(1);

    auto *settings = new QPushButton("Settings", this);
    settings->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    auto *accounts = new QPushButton("Accounts", this);
    accounts->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    auto *loans = new QPushButton("Loans", this);
    loans->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    auto *cash = new QPushButton("Cash", this);
    cash->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    auto *debts = new QPushButton("Debts", this);
    debts->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    vbox->addWidget(settings);
    vbox->addWidget(accounts);
    vbox->addWidget(loans);
    vbox->addWidget(cash);
    vbox->addWidget(debts);

    setLayout(vbox);
}

在我们的示例中,我们有一个垂直布局管理器。我们向其中放入了五个按钮。我们使所有按钮在两个方向上都可扩展。

auto *vbox = new QVBoxLayout(this);
vbox->setSpacing(1);

我们创建了 QVBoxLayout,并在子窗口部件之间设置了 1 像素的间距。

auto *settings = new QPushButton("Settings", this);
settings->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

我们创建了一个按钮,并为其设置了大小策略。子窗口部件由布局管理器管理。默认情况下,按钮在水平方向上扩展,在垂直方向上具有固定大小。如果我们想更改它,就设置一个新的大小策略。在我们的例子中,按钮在两个方向上都可扩展。

vbox->addWidget(settings);
vbox->addWidget(accounts);
...

我们使用 addWidget 方法将子窗口部件添加到布局管理器中。

setLayout(vbox);

我们为窗口设置了 QVBoxLayout 管理器。

  • main.cpp
#include <QApplication>
#include "vertical_box.h"

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    VerticalBox window;
    window.resize(240, 230);
    window.setWindowTitle("VerticalBox");
    window.show();
    return app.exec();
}
  • 按钮
    在下面的示例中,我们在窗口的客户区显示两个按钮。它们将被放置在窗口的右下角。

buttons.h

#pragma once
#include <QWidget>
#include <QPushButton>

class Buttons : public QWidget {
public:
    Buttons(QWidget *parent = nullptr);
private:
    QPushButton *okBtn;
    QPushButton *applyBtn;
};

buttons.cpp

#include <QVBoxLayout>
#include <QHBoxLayout>
#include "buttons.h"

Buttons::Buttons(QWidget *parent)
    : QWidget(parent) {
    auto *vbox = new QVBoxLayout(this);
    auto *hbox = new QHBoxLayout();

    okBtn = new QPushButton("OK", this);
    applyBtn = new QPushButton("Apply", this);

    hbox->addWidget(okBtn, 1, Qt::AlignRight);
    hbox->addWidget(applyBtn, 0);

    vbox->addStretch(1);
    vbox->addLayout(hbox);
}

假设我们想在窗口的右下角放置两个按钮。

auto *vbox = new QVBoxLayout(this);
auto *hbox = new QHBoxLayout();

我们创建了两个盒式布局管理器:一个垂直布局管理器和一个水平布局管理器。

okBtn = new QPushButton("OK", this);
applyBtn = new QPushButton("Apply", this);

我们创建了两个按钮。

hbox->addWidget(okBtn, 1, Qt::AlignRight);
hbox->addWidget(applyBtn, 0);

使用 addWidget 方法将按钮放置在水平布局管理器中。这些按钮右对齐。第一个参数是子窗口部件。第二个参数是拉伸因子,最后一个参数是对齐方式。通过将 “OK” 按钮的拉伸因子设置为 1,我们为它在窗口的左侧到右侧之间分配了空间。该窗口部件不会扩展到分配给它的所有空间。最后,Qt::AlignRight 常量将窗口部件对齐到分配空间的右侧。

vbox->addStretch(1);
vbox->addLayout(hbox);

我们通过调用 addStretch 方法在垂直盒式布局中放入一个空的、可扩展的空间。然后,我们将水平盒式布局添加到垂直盒式布局中。

main.cpp

#include <QApplication>
#include "buttons.h"

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    Buttons window;
    window.resize(290, 170);
    window.setWindowTitle("Buttons");
    window.show();
    return app.exec();
}
  • Qt5 嵌套布局
    下面示例的目的是展示布局管理器可以组合使用。通过组合即使是简单的布局,我们也可以创建复杂的对话框或窗口。为了实现布局嵌套,我们使用 addLayout 方法。

nesting.h

#pragma once
#include <QWidget>

class Layouts : public QWidget {
public:
    Layouts(QWidget *parent = nullptr);
};

nesting.cpp

#include <QVBoxLayout>
#include <QPushButton>
#include <QListWidget>
#include "nesting.h"

Layouts::Layouts(QWidget *parent)
    : QWidget(parent) {
    auto *vbox = new QVBoxLayout();
    auto *hbox = new QHBoxLayout(this);

    auto *lw = new QListWidget(this);
    lw->addItem("The Omen");
    lw->addItem("The Exorcist");
    lw->addItem("Notes on a scandal");
    lw->addItem("Fargo");
    lw->addItem("Capote");

    auto *add = new QPushButton("Add", this);
    auto *rename = new QPushButton("Rename", this);
    auto *remove = new QPushButton("Remove", this);
    auto *removeall = new QPushButton("Remove All", this);

    vbox->setSpacing(3);
    vbox->addStretch(1);
    vbox->addWidget(add);
    vbox->addWidget(rename);
    vbox->addWidget(remove);
    vbox->addWidget(removeall);
    vbox->addStretch(1);

    hbox->addWidget(lw);
    hbox->addSpacing(15);
    hbox->addLayout(vbox);

    setLayout(hbox);
}

在这个示例中,我们创建了一个窗口,它由四个按钮和一个列表部件组成。这些按钮被分组在一个垂直列中,并放置在列表部件的右侧。如果我们调整窗口大小,列表部件也会随之调整大小。

auto *vbox = new QVBoxLayout();

QVBoxLayout 是按钮所在的列。

auto *hbox = new QHBoxLayout(this);

QHBoxLayout 是这些窗口部件的基础布局。

auto *lw = new QListWidget(this);
lw->addItem("The Omen");
lw->addItem("The Exorcist");
lw->addItem("Notes on a scandal");
lw->addItem("Fargo");
lw->addItem("Capote");

创建了 QListWidget。

auto *add = new QPushButton("Add", this);
auto *rename = new QPushButton("Rename", this);
auto *remove = new QPushButton("Remove", this);
auto *removeall = new QPushButton("Remove All", this);

在这里我们创建了四个按钮。

vbox->setSpacing(3);
vbox->addStretch(1);
vbox->addWidget(add);
vbox->addWidget(rename);
vbox->addWidget(remove);
vbox->addWidget(removeall);
vbox->addStretch(1);

创建了包含四个按钮的垂直盒式布局。我们在按钮之间设置了一些小间距。注意,我们在垂直盒式布局的顶部和底部都添加了拉伸因子。这样,按钮就会在垂直方向上居中。

hbox->addWidget(lw);
hbox->addSpacing(15);
hbox->addLayout(vbox);

列表部件和按钮的垂直盒式布局被放置到水平盒式布局中。addLayout 方法用于将一个布局添加到另一个布局中。

setLayout(hbox);

我们为父窗口设置了基础布局。

main.cpp

#include <QApplication>
#include "nesting.h"

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    Layouts window;
    window.setWindowTitle("Layouts");
    window.show();
    return app.exec();
}
  • Qt5 FormLayout
    QFormLayout 是一个简单的布局管理器,用于管理输入窗口部件及其相关标签组成的表单。它以两列的形式排列其子窗口部件。左列由标签组成,右列由像 QLineEdit 或 QSpinBox 这样的输入窗口部件组成。

form.h

#pragma once
#include <QWidget>

class FormEx : public QWidget {
public:
    FormEx(QWidget *parent = nullptr);
};

form.cpp

#include <QFormLayout>
#include <QLabel>
#include <QLineEdit>
#include "form.h"

FormEx::FormEx(QWidget *parent)
    : QWidget(parent) {
    auto *nameEdit = new QLineEdit(this);
    auto *addrEdit = new QLineEdit(this);
    auto *occpEdit = new QLineEdit(this);

    auto *formLayout = new QFormLayout;
    formLayout->setLabelAlignment(Qt::AlignRight | Qt::AlignVCenter);
    formLayout->addRow("Name:", nameEdit);
    formLayout->addRow("Email:", addrEdit);
    formLayout->addRow("Age:", occpEdit);

    setLayout(formLayout);
}

这个示例创建了一个由三个标签和三个行编辑框组成的表单。

auto *formLayout = new QFormLayout;

创建了一个 QFormLayout 的实例。

formLayout->setLabelAlignment(Qt::AlignRight | Qt::AlignVCenter);

使用 setLabelAlignment 方法,我们设置了标签窗口部件的对齐方式。

formLayout->addRow("Name:", nameEdit);

addRow 方法在表单布局的底部添加一个新行,并带有给定的标签和输入窗口部件。

main.cpp

#include <QApplication>
#include "form.h"

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    FormEx window;
    window.setWindowTitle("Form example");
    window.show();
    return app.exec();
}



  • Qt5 QGridLayout
    QGridLayout 将其窗口部件放置在一个网格中。它是一个功能强大的布局管理器。

calculator.h

#pragma once
#include <QWidget>

class Calculator : public QWidget {
public:
    Calculator(QWidget *parent = nullptr);
};

calculator.cpp

#include <QGridLayout>
#include <QPushButton>
#include "calculator.h"

Calculator::Calculator(QWidget *parent)
    : QWidget(parent) {
    auto *grid = new QGridLayout(this);
    grid->setSpacing(2);

    QVector<QString> values({ "7", "8", "9", "/",
        "4", "5", "6", "*",
        "1", "2", "3", "-",
        "0", ".", "=", "+"
    });

    int pos = 0;

    for (int i=0; i<4; i++) {
        for (int j=0; j<4; j++) {
            auto *btn = new QPushButton(values[pos], this);
            btn->setFixedSize(40, 40);
            grid->addWidget(btn, i, j);
            pos++;
        }
    }

    setLayout(grid);
}

我们创建了一个计算器的框架。

auto *grid = new QGridLayout(this);
grid->setSpacing(2);

我们创建了网格布局,并在子窗口部件之间设置了 2 像素的间距。

QVector<QString> values({ "7", "8", "9", "/",
    "4", "5", "6", "*",
    "1", "2", "3", "-",
    "0", ".", "=", "+"
});

这些是显示在按钮上的字符。

for (int i=0; i<4; i++) {
    for (int j=0; j<4; j++) {
        auto *btn = new QPushButton(values[pos], this);
        btn->setFixedSize(40, 40);
        grid->addWidget(btn, i, j);
        pos++;
    }
}

我们将十六个窗口部件放置到网格布局中。每个按钮都有固定的大小。

main.cpp

#include <QApplication>
#include "calculator.h"

int main(int argc, char *argv[]) {
    QApplication app(argc, argv);
    Calculator window;
    window.setWindowTitle("Calculator");
    window.show();
    return app.exec();
}
控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言