七、布局管理和空间间隔
- Vertical Layout:垂直布局
- Horizontal Layout:横向布局
- Grid Layout:网格布局
- Form Layout:表单布局
- Horizontal Spacer:水平间隔
- Vertical Spacer:垂直间隔
我们重点介绍代码实现的布局,GridLayout网格布局和FormLayout表单布局
7.1 QGridLayout 网格布局
首先我们创建QWidget工程
widget.h头文件
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<QGridLayout> //网格控件
#include<QLabel> //标签控件
#include<QPushButton> //命令按钮控件
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
QGridLayout *gl;
QPushButton *pb1;
QPushButton *pb2;
QPushButton *pb3;
QPushButton *pb4;
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
首先我们引入三个头文件分别是网格布局控件QGridLayout、标签控件QLabel和命令按钮控件QPushButton,QLabel和QPushButton后面会详细介绍,我们这里只要知道这两个是控制标签和命令按钮的就行。
创建一个QGridLayout对象用于在源文件中进行网格布局和四个QPushButton对象用于在源文件中进行命令按钮。
widget.cpp源文件
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
pb1=new QPushButton(this);
pb1->setText("第一区:顶部菜单栏选项");
pb1->setFixedHeight(40); //设置高度
pb1->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
/*
QSizePolicy
此属性包含小部件的默认布局行为
如果有一个QLayout管理这个小部件的子部件,
则使用该布局指定的大小策略。如果没有这样的QLayout,则使用该函数的结果。
默认策略是Preferred/Preferred,
这意味着小部件可以自由调整大小,
但更倾向于使用sizeHint()返回的大小。
类似按钮的小部件设置大小策略,
以指定它们可以水平拉伸,但垂直固定。
这同样适用于lineedit控件
(如QLineEdit、QSpinBox或可编辑的QComboBox)和其他控件
*/
pb2=new QPushButton(this);
pb2->setText("第二区:侧边栏选项");
pb2->setFixedWidth(100); //设置宽度
pb2->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
pb3=new QPushButton(this);
pb3->setText("第三区:底部选项");
pb3->setFixedHeight(40);
pb3->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
pb4=new QPushButton(this);
pb4->setText("第四区:子窗体选项");
pb4->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
gl=new QGridLayout();
gl->setContentsMargins(0,0,0,0);
/*
setContentsMargins
设置要围绕布局使用的左、上、右和下边距。
默认情况下,QLayout使用样式提供的值。在大多数平台上,所有方向的边距都是11像素。
*/
//gl->setMargin(30);
/*
* 设置控件与窗体的左右边距
* 这个功能已经过时了。提供它是为了保持旧源代码的工作。我们强烈建议不要在新代码中使用它。
*/
gl->setSpacing(0);
/*
* 各个控件之间的上下间距
* 此函数将垂直和水平间距设置为spacing。
*/
gl->addWidget(pb1,0,1);
gl->addWidget(pb2,0,0,3,1);
gl->addWidget(pb3,2,1);
gl->addWidget(pb4,1,1);
/*
*addWidget(QWidget * widget, int fromRow, int fromColumn, int rowSpan, int columnSpan,
Qt::Alignment alignment = 0)
QWidget * widget:需要添加的widget
int fromRow:所在行
int fromColumn:所在列
int rowSpan:所占行数
int columnSpan:所占列数
alignment:对齐方式
*/
setLayout(gl);
/*
* 将此小部件的布局管理器设置为layout。
如果这个小部件上已经安装了布局管理器,
那么QWidget将不允许您安装其他布局管理器。
您必须首先删除现有的布局管理器(由layout()返回),
然后才能使用新布局调用setLayout()。
如果layout是另一个小部件上的布局管理器,
setLayout()将表示该布局并使其成为该小部件的布局管理器。
*/
}
Widget::~Widget()
{
delete ui;
}
详解上面涉及到的函数:
void QWidget::setFixedHeight(int h):
在不改变宽度的情况下,将小部件的最小高度和最大高度设置为h。
与此同时还有其他函数:
void QWidget::setFixedSize(const QSize &s):将小部件的最小和最大尺寸设置为s,从而防止它不断增长或缩小。
void QWidget::setFixedSize(int w, int h):将小部件的宽度设置为w,高度设置为h。
void QWidget::setFixedWidth(int w):在不改变高度的情况下,将小部件的最小和最大宽度设置为w。
void QWidget::setSizePolicy(QSizePolicy::Policy horizontal, QSizePolicy::Policy vertical):
将小部件的大小策略设置为水平和垂直,具有标准拉伸,没有高度换宽度。
对于QSizePolicy::Policy的参数QT提供七种参数:
常量 | 值 | 描述 |
---|---|---|
QSizePolicy::Fixed | 0 | QWidget::sizeHint()是唯一可接受的替代方法,因此小部件永远不能增长或缩小(例如,按钮的垂直方向)。 |
QSizePolicy::Minimum | GrowFlag | sizeHint()是最小的,也是足够的。小部件可以扩展,但它变大没有好处(例如,按钮的水平方向)。它不能小于sizeHint()提供的大小。 |
QSizePolicy::Maximum | ShrinkFlag | sizeHint()是一个最大值。如果其他部件需要空间(例如分隔线),则小部件可以任意缩小而不会损害。它不能大于sizeHint()提供的大小。 |
QSizePolicy::Preferred | GrowFlag | ShrinkFlag | sizeHint()是最好的,但是小部件可以缩小,但仍然有用。小部件可以展开,但是它比sizeHint()(默认的QWidget策略)大 |
QSizePolicy::Expanding | GrowFlag | ShrinkFlag | ExpandFlag | sizeHint()是一个合理的大小,但是小部件可以缩小并且仍然有用。小部件可以利用额外的空间,所以它应该得到尽可能多的空间(例如,水平滑块的水平方向)。 |
QSizePolicy::MinimumExpanding | GrowFlag | ExpandFlag | sizeHint()是最小的,也是足够的。小部件可以利用额外的空间,所以它应该得到尽可能多的空间(例如,水平滑块的水平方向)。 |
QSizePolicy::Ignored | ShrinkFlag | GrowFlag | IgnoreFlag | sizeHint()被忽略。小部件将获得尽可能多的空间。 |
在这个例子中,我们用到的是Expanding参数,意思就是能占多大空间就占多大空间,并且可以缩小,但是实际我们运行发现并不能把按钮缩小,这是因为官方说的小部件可以缩小,是把窗口变小,这些控件才会跟着缩小。
如果我们把下面代码注释掉
pb4->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
则运行结果为
我们发现这些控件并不紧凑在一起了。
void QLayout::setContentsMargins(int left, int top, int right, int bottom):
设置要围绕布局使用的左、上、右和下边距。默认情况下,QLayout使用样式提供的值。在大多数平台上,所有方向的边距都是11像素。
如果我们改为这样:
gl->setContentsMargins(20,20,20,20);
void QLayout::setMargin(int margin):
设置控件的与窗体的边距。这个功能已经过时了。提供它是为了保持旧源代码的工作。我们强烈建议不要在新代码中使用它。
void QGridLayout::setSpacing(int spacing):
设置各个控件的上下水平间距。
void QGridLayout::addWidget(QWidget * widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment = 0):
QWidget * widget:需要添加的widget
int fromRow:所在行
int fromColumn:所在列
int rowSpan:所占行数
int columnSpan:所占列数
alignment:对齐方式
void QWidget::setLayout(QLayout *layout):
将此小部件的布局管理器设置为layout。如果这个小部件上已经安装了布局管理器,那么QWidget将不允许您安装其他布局管理器。您必须首先删除现有的布局管理器(由layout()返回),然后才能使用新布局调用setLayout()。如果layout是另一个小部件上的布局管理器,setLayout()将表示该布局并使其成为该小部件的布局管理器。
总结:setLayout()函数是Qt中的一个函数,用于设置QWidget中的布局管理器。它接受一个QLayout对象作为参数,并将该布局管理器应用于QWidget。
7.2 QFormLayout 表单布局
首先我们创建widget工程
Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include<QFormLayout>
#include<QLineEdit>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
QFormLayout *fl;
QLineEdit *le1;
QLineEdit *le2;
QLineEdit *le3;
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
引入QFormLayout表单布局头文件和QLineEdit编辑头文件。
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
setFixedSize(250,250);
fl=new QFormLayout(this);
le1=new QLineEdit(); //输入学号
le2=new QLineEdit(); //输入姓名
le3=new QLineEdit(); //输入学校
fl->addRow("学号",le1);
fl->addRow("姓名",le2);
fl->addRow("学校",le3);
fl->setSpacing(20);
//把标签单独显示一行
//fl->setRowWrapPolicy(QFormLayout::WrapAllRows);
//把标签和输入框显示在一行
fl->setRowWrapPolicy(QFormLayout::WrapLongRows);
//把标签对齐
fl->setLabelAlignment(Qt::AlignLeft);
}
Widget::~Widget()
{
delete ui;
}
下面详解上面涉及到的函数
void QFormLayout::addRow(QWidget *label, QWidget *field):
在此表单布局的底部添加具有给定标签和字段的新行。
void setRowWrapPolicy(QFormLayout::RowWrapPolicy policy):
它来自RowWrapPolicy。
此属性保留表单的行换行方式
默认值取决于小部件或应用程序样式。对于Qt扩展样式,默认是WrapLongRows;对于其他样式,默认是DontWrapRows。如果您希望将每个标签显示在其关联字段的上方(而不是旁边),请将此属性设置为WrapAllRows。
关于QFormLayout::RowWrapPolicy,Qt给出了三种参数
常量 | 值 | 描述 |
---|---|---|
QFormLayout::DontWrapRows | 0 | 字段总是放在它们的标签旁边。这是除了Qt扩展样式之外的所有样式的默认策略。 |
QFormLayout::WrapLongRows | 1 | 标签被赋予足够的水平空间来容纳最宽的标签,其余的空间留给字段。如果字段对的最小大小大于可用空间,则将字段换行到下一行。这是Qt扩展样式的默认策略。 |
QFormLayout::WrapAllRows | 2 | 字段总是布局在它们的标签下面 |
void setLabelAlignment(Qt::Alignment alignment):
它来自Qt::Alignment。
此属性保持标签的水平对齐
默认值取决于小部件或应用程序样式。对于QCommonStyle派生的样式,除了QPlastiqueStyle,默认是Qt::AlignLeft;对于其他样式,默认是Qt::AlignRight。
关于Qt::Alignment,Qt也给出很多参数
常量 | 值 | 描述 |
---|---|---|
Qt::AlignLeft | 0x0001 | 与左边缘对齐。 |
Qt::AlignRight | 0x0002 | 与右边缘对齐。 |
Qt::AlignHCenter | 0x0004 | 在可用空间中水平居中。 |
Qt::AlignJustify | 0x0008 | 对可用空间中的文本进行校验。 |
常量 | 值 | 描述 |
---|---|---|
Qt::AlignTop | 0x0020 | 与顶部对齐。 |
Qt::AlignBottom | 0x0040 | 与底部对齐。 |
Qt::AlignVCenter | 0x0080 | 在可用空间中垂直居中。 |
Qt::AlignBaseline | 0x0100 | 与基线对齐。 |