Qt学习(19)——布局管理

在这部分中将讨论小部件的布局管理。我们提到QHBoxLayoutQVBoxLayoutQFormLayoutQGridLayout管理器。
一个典型的应用程序由各种小部件组成。这些小部件放置在布局内。程序员必须管理应用程序的布局。在Qt5中我们有两种选择:

  • 绝对定位
  • 布局管理

绝对定位

程序员以像素为单位指定每个小部件的位置和大小。当我们使用绝对定位时,我们必须理解几件事情:

  • 如果我们调整窗口的大小,窗口小部件的大小和位置不会改变。
  • 应用程序在各种平台上看起来不同(通常很差)。
  • 更改应用程序中的字体可能会破坏布局。
  • 如果我们决定改变布局,我们必须完全重做我们的布局,这是乏味和耗时的。

虽然可能会出现使用绝对定位的情况。但大多数情况下,都会使用布局管理器。

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

class Absolute : public QWidget {

 public:
     Absolute(QWidget *parent = 0);
};

Absolute::Absolute(QWidget *parent)
    : QWidget(parent) {

  QTextEdit *ledit = new QTextEdit(this); //setGeometry()方法用于以绝对坐标在窗口上定位控件。
  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();
}

程序创建一个QTextEdit控件并手动进行定位。setGeometry()方法做了两件事:它将窗口控件定位到绝对坐标并调整窗口小部件的大小。
这里写图片描述 这里写图片描述

QVBoxLayout

QVBoxLayout 类将控件垂直排列。使用addWidget() 方法将控件添加到布局中。

//verticalbox.h
#pragma once

#include <QWidget>

class VerticalBox : public QWidget {

  public:
    VerticalBox(QWidget *parent = 0);
};
//verticalbox.cpp
#include "verticalbox.h"
#include <QVBoxLayout>
#include <QPushButton>

VerticalBox::VerticalBox(QWidget *parent)
    : QWidget(parent) {

  QVBoxLayout *vbox = new QVBoxLayout(this);//创建QVBoxLayout
  vbox->setSpacing(1); //将子窗口控件间距设置为1px

  QPushButton *settings = new QPushButton("Settings", this);
  settings->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
  QPushButton *accounts = new QPushButton("Accounts", this);
  accounts->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
  QPushButton *loans = new QPushButton("Loans", this);
  loans->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
  QPushButton *cash = new QPushButton("Cash", this);
  cash->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
  QPushButton *debts = new QPushButton("Debts", this);
  debts->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
  //创建一个按钮并为其设置大小策略。子窗口控件由布局管理器管理。
  //默认情况下,按钮水平扩展并垂直固定大小。如果想要改变它,需要设置一个新的大小政策。

  //使用addWidget()方法将控件添加到布局管理器。
  vbox->addWidget(settings);
  vbox->addWidget(accounts);
  vbox->addWidget(loans);
  vbox->addWidget(cash);
  vbox->addWidget(debts);

  setLayout(vbox); //为窗口设置QVBoxLayout管理器。
}

将五个按钮放入垂直布局管理器中,使所有的按钮在横向展开。

//main.cpp
#include "verticalbox.h"
#include <QApplication>

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

在以下示例中,将两个按钮显示在窗口的右下角。

//buttons.h
#pragma once

#include <QWidget>
#include <QPushButton>

class Buttons : public QWidget {

  public:
    Buttons(QWidget *parent = 0);

  private:
    QPushButton *okBtn;
    QPushButton *applyBtn;
};
//buttons.cpp
#include "buttons.h"
#include <QVBoxLayout>
#include <QHBoxLayout>

Buttons::Buttons(QWidget *parent)
    : QWidget(parent) {

  //创建两个框布局管理器:一个垂直框和一个水平框布局管理器。
  QVBoxLayout *vbox = new QVBoxLayout(this);
  QHBoxLayout *hbox = new QHBoxLayout();

  //创建两个按钮
  okBtn = new QPushButton("OK", this);
  applyBtn = new QPushButton("Apply", this);

  //将按钮置于水平布局管理器内,使用addWidget()将按钮右对齐,
  //这个函数包含三个参数,第一个参数是控件,第二个是拉伸因子,第三个是对齐方式
  //将OK按钮的拉伸系数设置为1,从窗口左侧到右侧进行空间分配,这样控件就不会扩展到分配给他的所有控件
  //最后通过Qt::AlignRight将控件与分配空间右对齐
  hbox->addWidget(okBtn, 1, Qt::AlignRight);
  hbox->addWidget(applyBtn, 0);

  //通过调用addStretch()方法将空的可扩展空间放入垂直框中。
  //然后将水平框布局添加到垂直框布局。
  vbox->addStretch(1);
  vbox->addLayout(hbox);
}
//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();
}

嵌套布局

这个例子的想法是将布局管理器进行组合显示,通过简单的布局组合可以创建出复杂的对话窗和窗口。使用addLayout() 方法来组合布局。

//nesting.h
#pragma once

#include <QWidget>

class Layouts : public QWidget {

  public:
    Layouts(QWidget *parent = 0);
};
//nesting.cpp
#include <QVBoxLayout>
#include <QPushButton>
#include <QListWidget>
#include "nesting.h"

Layouts::Layouts(QWidget *parent)
    : QWidget(parent) {

  QVBoxLayout *vbox = new QVBoxLayout(); //用于放置按钮
  QHBoxLayout *hbox = new QHBoxLayout(this); //创建基本布局

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

  // 创建四个按钮
  QPushButton *add = new QPushButton("Add", this);
  QPushButton *rename = new QPushButton("Rename", this);
  QPushButton *remove = new QPushButton("Remove", this);
  QPushButton *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);

  //列表和垂直方框按钮放置在水平框布局中。addLayout()方法用于将布局添加到另一个布局中。
  hbox->addWidget(lw);
  hbox->addSpacing(15);
  hbox->addLayout(vbox);

  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();
}

QFormLayout

QFormLayout 是一个简单的布局管理器,用于管理输入窗口及其相关标签的形式。它以两列的形式列出了它的子窗口。左列由标签组成,右列由输入窗口组成,如QLineEditQSpinBox

//form.h
#pragma once

#include <QWidget>

class FormEx : public QWidget {

  public:
    FormEx(QWidget *parent = 0);
};
//form.cpp
#include <QFormLayout>
#include <QLabel>
#include <QLineEdit>
#include "form.h"

FormEx::FormEx(QWidget *parent)
    : QWidget(parent) {

  QLineEdit *nameEdit = new QLineEdit(this);
  QLineEdit *addrEdit = new QLineEdit(this);
  QLineEdit *occpEdit = new QLineEdit(this);

  QFormLayout *formLayout = new QFormLayout; //创建QFormLayout的实例。
  formLayout->setLabelAlignment(Qt::AlignRight | Qt::AlignVCenter); //使用setLabelAlignment()方法设置标签的对齐方式。

  //使用addRow()方法给标签和输入窗口在窗体布局的底部添加一个新行。
  formLayout->addRow("Name:", nameEdit);
  formLayout->addRow("Email:", addrEdit);
  formLayout->addRow("Age:", occpEdit);

  setLayout(formLayout);
}

该示例创建一个由三个标签和三个线编辑组成的表单。

//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();
}

QGridLayout

QGridLayout将控件放在网格中,是一个强大的布局管理器。

//calculator.h
#pragma once

#include <QWidget>

class Calculator : public QWidget {

  public:
    Calculator(QWidget *parent = 0);

};
//calculator.cpp
#include <QGridLayout>
#include <QPushButton>
#include "calculator.h"

Calculator::Calculator(QWidget *parent)
    : QWidget(parent) {

  // 创建网格布局并在子窗口控件之间设置2px间隔
  QGridLayout *grid = new QGridLayout(this);
  grid->setSpacing(2);

  // 按钮上显示的字符
  QList<QString> values({ "7", "8", "9", "/", 
    "4", "5", "6", "*",
    "1", "2", "3", "-",
    "0", ".", "=", "+"
  });

  int pos = 0;

  // 在网格布局中放置了16个按钮,每个按钮都有固定的尺寸。
  for (int i=0; i<4; i++) {
   for (int j=0; j<4; j++) {

     QPushButton *btn = new QPushButton(values[pos], this);
     btn->setFixedSize(40, 40);
     grid->addWidget(btn, i, j);
     pos++;
   }
  }  

  setLayout(grid);
}

创建了一个计算器的骨架。

//main.cpp
#include <QApplication>
#include "calculator.h"

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

  QApplication app(argc, argv); 

  Calculator window;

  window.move(300, 300);
  window.setWindowTitle("Calculator");
  window.show();

  return app.exec();
}

复习QGridLayout

下一个示例中,使用QGridLayout管理器创建一个更复杂的窗口.

//review.h
#pragma once

#include <QWidget>

class Review : public QWidget {

  public:
    Review(QWidget *parent = 0);
};
//review.cpp
#include <QGridLayout>
#include <QLabel>
#include <QLineEdit>
#include <QTextEdit>
#include "review.h"

Review::Review(QWidget *parent)
    : QWidget(parent) {

  QGridLayout *grid = new QGridLayout(this);
  // 使用setVerticalSpacing()方法添加垂直间距,使用setHorizo​​ntalSpacing()方法添加水平间距。
  grid->setVerticalSpacing(15);
  grid->setHorizontalSpacing(10);

  QLabel *title = new QLabel("Title:", this);
  // 这些代码行创建一个标签并将其放入网格布局中。
  // addWidget()方法有五个参数。
  // 第一个参数是子窗口控件,在这个例子中是一个标签。
  // 接下来的两个参数是放置标签的网格中的行和列。,
  // 最后一个参数是rowspan和colspan。这些参数指定当前窗口小部件将跨越多少行。
  // 在这个例子中,标签将只跨越一列和一行。
  grid->addWidget(title, 0, 0, 1, 1);
  // setAlignment()方法设置单元格中标题标签对齐方式。水平方向右对齐,垂直方向居中。
  title->setAlignment(Qt::AlignRight | Qt::AlignVCenter);

  QLineEdit *edt1 = new QLineEdit(this);
  grid->addWidget(edt1, 0, 1, 1, 1);

  QLabel *author = new QLabel("Author:", this);
  grid->addWidget(author, 1, 0, 1, 1);
  author->setAlignment(Qt::AlignRight | Qt::AlignVCenter);

  QLineEdit *edt2 = new QLineEdit(this);
  grid->addWidget(edt2, 1, 1, 1, 1);

  QLabel *review = new QLabel("Review:", this);
  grid->addWidget(review, 2, 0, 1, 1);
  review->setAlignment(Qt::AlignRight | Qt::AlignTop);

  QTextEdit *te = new QTextEdit(this);
  // QTextEdit放在第三行和第二列中;跨越三行一列。
  grid->addWidget(te, 2, 1, 3, 1);

  setLayout(grid);
}

该代码创建了一个窗口,可用于输入作者,标题和书籍评论。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值