Qt中窗口组件的基类QWidget有两组重载函数用于实现窗口组件的绝对定位:
//定位窗口的坐标
void move(const QPoint &) void move(int x, int y)
//定义窗口占据的大小
void resize(const QSize &) void resize(int w, int h)
存在的问题:
(1) 程序员需要计算/规划组件的坐标
(2) 组件的大小和位置不能自适应所在父窗口的变化
1. QLayout的引入
Qt采用的解决方案是布局管理器QLayout。布局管理器能根据界面组件进行布局管理:(1)能够自动排列窗口中的界面组件;(2)窗口变化后能自动更新界面的大小。
QLayout是Qt中布局管理器的抽象基类,通过继承QLayout可实现功能各异的布局管理器。在Qt中由QLayout衍生出若干个实现项目开发中常用的布局管理器子类:垂直/水平布局管理器QBoxLayout、网格布局管理器QGridLayout、表单布局管理器QFormLayout、栈式布局管理器QStackedLayout。
QObject类是所以Qt类的基类,也是Qt对象模型的核心;QLayoutItem为布局操作提供了抽象条款。强调:布局管理器不是界面部件,而是界面部件的定位策略。
2. 垂直/水平布局管理器QBoxLayout
2.1 垂直布局管理器
//Widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QVBoxLayout>
class Widget : public QWidget
{
Q_OBJECT
private:
//定义4个按钮在Widget内
QPushButton Btn1;
QPushButton Btn2;
QPushButton Btn3;
QPushButton Btn4;
void VBoxLayout();
public:
Widget(QWidget *parent = 0);
~Widget();
};
Widget::Widget(QWidget *parent) : QWidget(parent), Btn1(this), Btn2(this), Btn3(this), Btn4(this)
{
this->VBoxLayout();
}
#endif // WIDGET_H
//Widget.cpp
void Widget::VBoxLayout()
{
//QVBoxLayout vb(this);
QVBoxLayout *vb = new QVBoxLayout; //一定要动态分配
//按钮的提示信息
Btn1.setText("1");
//按钮大小的最小值
Btn1.setMinimumSize(160, 30);
//设置按钮的大小策略,Expanding表示可随着父窗口的大小变化而发生改变
Btn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
Btn2.setText("2");
Btn2.setMinimumSize(160, 30);
Btn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
Btn3.setText("3");
Btn3.setMinimumSize(160, 30);
Btn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
Btn4.setText("4");
Btn4.setMinimumSize(160, 30);
Btn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
//将按钮对象添加到布局管理器
vb->addWidget(&Btn1);
vb->addWidget(&Btn2);
vb->addWidget(&Btn3);
vb->addWidget(&Btn4);
//设置每个按钮之间的间隔
vb->setSpacing(30);
//两种方法设置按钮的变化比例系数
vb->setStretchFactor(&Btn3, 2);
vb->setStretch(0, 6); //0表示index,第一个被加入布局管理器的组件被自动编号为0
//将当前widget交付布局管理器vb管理
setLayout(vb);
}
//main.c
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
运行:
布局管理器对象的生成必须动态分配,若在栈中生成,那么该函数退出后布局对象将被销毁,布局效果将失效。另外动态生成的布局对象并不需要程序员代码实现销毁。将Widget交付布局管理器托管后,管理器的父类对象即为widget,在父类Widget对象销毁后,会自动销毁Widget对象的所有子类,包括动态生成的布局管理器。
可以在上面VBoxLayout()函数中打印管理器对象的父对象的地址,该地址地位windget对象的地址,即this指针:
qDebug() << this;
qDebug() << vb->parent();
运行后:
2.2 水平布局管理器
#include <