Qt的布局系统提供了一个简单的和强有力的方式,来自动排列窗口子控件布局。QHBoxLayout、QVBoxLayout、QGridLayout和QFormLayout。这些类都派生自QLayout,QLayout又派生自QObject(非QWidget),布局窗口自动地把子窗口按照它们被构造地顺序进行布局。要生成更复杂的布局,可以在其它布局里面嵌入另一个布局。
所有QWidget子类可以使用布局来管理他们的子控件。QWidget::setLayout()函数可以为一个控件布局。
一、QHBoxLayout、QVBoxLayout
QHBoxLayout:水平布局,在水平方向上排列控件,即:左右排列。
QVBoxLayout:垂直布局,在垂直方向上排列控件,即:上下排列。
常用接口
我们可以看到,默认的外边距为0,为了美观性我们可以设置下外边距。
- setMargin(int)
- setContentsMargins(int left, int top, int right, int bottom);
- setContentsMargins(const QMargins &margins)
setMargin可以设置左、上、右、下的外边距,设置之后,他们的外边距是相同的。
setContentsMargins与其功能相同,但是可以将左、上、右、下的外边距设置为不同的值。
- setSpacing(int)-设置子控件之间间距
- addStretch()-添加了一个伸缩空间(QSpacerItem)。
- addWidget(QWidget *, int stretch = 0, Qt::Alignment alignment = 0)--添加控件
- setDirection(Direction)-设置布局方向
- setStretchFactor(QWidget *w, int stretch);-设置控件、布局的拉伸系数
- setStretchFactor(QLayout *l, int stretch);-设置控件、布局的拉伸系数
简单示例
QHBoxLayout *pHLayout = new QHBoxLayout();
pHLayout->addStretch();
// 水平居左 垂直居上
pHLayout->addWidget(pButton1, 0 , Qt::AlignLeft | Qt::AlignTop);
pHLayout->addWidget(pButton2, 0 , Qt::AlignLeft | Qt::AlignTop);
pHLayout->addWidget(pButton3);
// 水平居左 垂直居下
pHLayout->addWidget(pButton4, 0 , Qt::AlignLeft | Qt::AlignBottom);
pHLayout->addWidget(pButton5, 0 , Qt::AlignLeft | Qt::AlignBottom);
pHLayout->setSpacing(10);
二、格栅布局(QGridLayout)
QGridLayout:格栅布局,也被称作网格布局(多行多列)。栅格布局将位于其中的窗口部件放入一个网状的栅格之中。QGridLayout需要将提供给它的空间划分成的行和列,并把每个窗口部件插入并管理到正确的单元格。
一般情况下我们都是把某个窗口部件放进栅格布局的一个单元中,但窗口部件有时也可能会需要占用多个单元。这时就需要用到addWidget()方法的一个重载版本,原型如下:
- void addWidget(QWidget *, int row, int column, int rowSpan, int columnSpan, Qt::Alignment = 0);
这个单元将从row和column开始,扩展到rowSpan和columnSpan指定的倍数的行和列。如果rowSpan或columnSpan的值为-1,则窗口部件将扩展到布局的底部或者右边边缘处。
在创建栅格布局完成后,就可以使用addWidget(),addItem(),以及addLayout()方法向其中加入窗口部件,以及其它的布局。
常用接口
addWidget(QWidget *, int row, int column, Qt::Alignment = 0)
addWidget(QWidget *, int row, int column, int rowSpan, int columnSpan, Qt::Alignment = 0)
添加窗口部件至布局。
这个单元将从row和column开始,扩展到rowSpan和columnSpan指定的倍数的行和列。如果rowSpan或columnSpan的值为-1,则窗口部件将扩展到布局的底部或者右边边缘处,Qt::Alignment为对齐方式。
-addLayout(QLayout *, int row, int column, Qt::Alignment = 0)
-addLayout(QLayout *, int row, int column, int rowSpan, int columnSpan, Qt::Alignment = 0)
和addWidget类似,这个是添加布局。
setRowStretch(int row, int stretch)
setColumnStretch(int column, int stretch)
设置行/列的伸缩空间
和QBoxLayout的addStretch功能类似。
setSpacing(int spacing)
setHorizontalSpacing(int spacing)
setVerticalSpacing(int spacing)
设置间距
setSpacing()可以同时设置水平、垂直间距,设置之后,水平、垂直间距相同。
setHorizontalSpacing()、setVerticalSpacing()可以分别设置水平间距、垂直间距。
setRowMinimumHeight(int row, int minSize)
设置行最小高度
setColumnMinimumWidth(int column, int minSize)
设置列最小宽度
columnCount()
获取列数
rowCount()
获取行数
setOriginCorner(Qt::Corner)
设置原始方向
和QBoxLayout的setDirection功能类似。
示例
下面我们以企鹅为例,来讲解如何使用QGridLayout。
// 构建控件 头像、用户名、密码输入框等
QLabel *pImageLabel = new QLabel(this);
QLineEdit *pUserLineEdit = new QLineEdit(this);
QLineEdit *pPasswordLineEdit = new QLineEdit(this);
QCheckBox *pRememberCheckBox = new QCheckBox(this);
QCheckBox *pAutoLoginCheckBox = new QCheckBox(this);
QPushButton *pLoginButton = new QPushButton(this);
QPushButton *pRegisterButton = new QPushButton(this);
QPushButton *pForgotButton = new QPushButton(this);
pLoginButton->setFixedHeight(30);
pUserLineEdit->setFixedWidth(200);
// 设置头像
QPixmap pixmap(":/Images/logo");
pImageLabel->setFixedSize(90, 90);
pImageLabel->setPixmap(pixmap);
pImageLabel->setScaledContents(true);
// 设置文本
pUserLineEdit->setPlaceholderText(QStringLiteral("QQ号码/手机/邮箱"));
pPasswordLineEdit->setPlaceholderText(QStringLiteral("密码"));
pPasswordLineEdit->setEchoMode(QLineEdit::Password);
pRememberCheckBox->setText(QStringLiteral("记住密码"));
pAutoLoginCheckBox->setText(QStringLiteral("自动登录"));
pLoginButton->setText(QStringLiteral("登录"));
pRegisterButton->setText(QStringLiteral("注册账号"));
pForgotButton->setText(QStringLiteral("找回密码"));
QGridLayout *pLayout = new QGridLayout();
// 头像 第0行,第0列开始,占3行1列
pLayout->addWidget(pImageLabel, 0, 0, 3, 1);
// 用户名输入框 第0行,第1列开始,占1行2列
pLayout->addWidget(pUserLineEdit, 0, 1, 1, 2);
pLayout->addWidget(pRegisterButton, 0, 4);
// 密码输入框 第1行,第1列开始,占1行2列
pLayout->addWidget(pPasswordLineEdit, 1, 1, 1, 2);
pLayout->addWidget(pForgotButton, 1, 4);
// 记住密码 第2行,第1列开始,占1行1列 水平居左 垂直居中
pLayout->addWidget(pRememberCheckBox, 2, 1, 1, 1, Qt::AlignLeft | Qt::AlignVCenter);
// 自动登录 第2行,第2列开始,占1行1列 水平居右 垂直居中
pLayout->addWidget(pAutoLoginCheckBox, 2, 2, 1, 1, Qt::AlignRight | Qt::AlignVCenter);
// 登录按钮 第3行,第1列开始,占1行2列
pLayout->addWidget(pLoginButton, 3, 1, 1, 2);
// 设置水平间距
pLayout->setHorizontalSpacing(10);
// 设置垂直间距
pLayout->setVerticalSpacing(10);
// 设置外间距
pLayout->setContentsMargins(10, 10, 10, 10);
setLayout(pLayout);
三、表单布局(QFormLayout)
QFormLayout管理输入型控件和关联的标签组成的那些Form表单。当要设计的界面是一种类似于两列和若干行组成的形式时,使用QFormLayout(表单布局)要比QGridLayout(栅格布局)更为方便些。
QFormLayout是一个方便的布局类,其中的控件以两列的形式被布局在表单中。左列包括标签,右列包含输入控件,例如:QLineEdit、QSpinBox等。
我们可以通过addRow(const QString &labelText, QWidget *field)来创建一个带有给定文本的QLabel及QWidget控件行,它们可以自动的设置为伙伴关系。
常用接口
- setRowWrapPolicy(RowWrapPolicy policy)-设置换行策略
- setWidget(int row, ItemRole role, QWidget *widget)-设置行row所对应的控件,如果role为LabelRole时,设置的为标签所对应的控件,如果role为FieldRole时,设置的为输入框所对应的控件。
- setSpacing(int spacing) -设置控件之间间距
- setHorizontalSpacing(int spacing) -设置水平间距
-
setVerticalSpacing(int spacing) -设置垂直间距
-
QWidget * QFormLayout::labelForField(QWidget * field)-通过field获取field对应的标签,这里不一定是QLabel,返回值为QWidget。