1.目前GUI开发方式:绝对定位
直接在像素级指定各个组件的位置和大小,但是组建的位置和大小无法自适应父窗口的变化
解决方案:布局管理器,提供相关的类对界面组件进行布局管理
- 能够自动排列窗口中的界面组件
- 窗口变化后自动更新界面组件的大小
2.QLayout是Qt中布局管理器的抽象基类
(1)QBoxLayout布局管理器:以水平或垂直的方式管理界面组件
原来的代码:
Widget::Widget(QWidget *parent) : QWidget(parent),
TestBtn1(this), TestBtn2(this), TestBtn3(this), TestBtn4(this)
{
initControl();
}
void Widget::initControl()
{
TestBtn1.setText("TestBtn1");
TestBtn1.move(20, 20);
TestBtn1.resize(160, 30);
TestBtn2.setText("TestBtn2");
TestBtn2.move(20, 70);
TestBtn2.resize(160, 30);
TestBtn3.setText("TestBtn3");
TestBtn3.move(20, 120);
TestBtn3.resize(160, 30);
TestBtn4.setText("TestBtn4");
TestBtn4.move(20, 170);
TestBtn4.resize(160, 30);
}
Widget::~Widget()
{
}
使用QBoxLayout后的代码:
Widget::Widget(QWidget *parent) : QWidget(parent),
TestBtn1(this), TestBtn2(this), TestBtn3(this), TestBtn4(this)
{
testVBoxLayout();
}
void Widget::testVBoxLayout()
{
QVBoxLayout* layout = new QVBoxLayout();
TestBtn1.setText("TestBtn1");
TestBtn2.setText("TestBtn2");
TestBtn3.setText("TestBtn3");
TestBtn4.setText("TestBtn4");
layout->addWidget(&TestBtn1);
layout->addWidget(&TestBtn2);
layout->addWidget(&TestBtn3);
layout->addWidget(&TestBtn4);
setLayout(layout);
}
Widget::~Widget()
{
}
但是该布局策略为:随着窗口放大,按钮的高度不变,只有宽度放大,如何改变呢?
Widget::Widget(QWidget *parent) : QWidget(parent),
TestBtn1(this), TestBtn2(this), TestBtn3(this), TestBtn4(this)
{
testHBoxLayout();
}
void Widget::testVBoxLayout() //垂直布局
{
QVBoxLayout* layout = new QVBoxLayout();
TestBtn1.setText("TestBtn1");
//让按钮 TestBtn1 在水平和垂直两个方向上,都自动拉伸填满父布局的可用空间。
TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn1.setMinimumSize(160,30); //设置按钮最小长度和高度
TestBtn2.setText("TestBtn2");
TestBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn2.setMinimumSize(160,30);
TestBtn3.setText("TestBtn3");
TestBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn3.setMinimumSize(160,30);
TestBtn4.setText("TestBtn4");
TestBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn4.setMinimumSize(160,30);
layout->setSpacing(30); //设置按钮之间的距离
layout->addWidget(&TestBtn1);
layout->addWidget(&TestBtn2);
layout->addWidget(&TestBtn3);
layout->addWidget(&TestBtn4);
setLayout(layout);
}
void Widget::testHBoxLayout() //水平布局
{
QHBoxLayout* layout = new QHBoxLayout();
TestBtn1.setText("TestBtn1");
//让按钮 TestBtn1 在水平和垂直两个方向上,都自动拉伸填满父布局的可用空间。
TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn1.setMinimumSize(160,30); //设置按钮最小长度和高度
TestBtn2.setText("TestBtn2");
TestBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn2.setMinimumSize(160,30);
TestBtn3.setText("TestBtn3");
TestBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn3.setMinimumSize(160,30);
TestBtn4.setText("TestBtn4");
TestBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn4.setMinimumSize(160,30);
layout->setSpacing(30); //设置按钮之间的距离
layout->addWidget(&TestBtn1);
layout->addWidget(&TestBtn2);
layout->addWidget(&TestBtn3);
layout->addWidget(&TestBtn4);
setLayout(layout);
}
3.布局管理器可以相互嵌套,形成更加复杂的布局方式
void Widget::testVHBoxLayout() //嵌套布局
{
QHBoxLayout* hlayout1 = new QHBoxLayout();
QHBoxLayout* hlayout2 = new QHBoxLayout();
QVBoxLayout* vlayout = new QVBoxLayout();
TestBtn1.setText("TestBtn1");
//让按钮 TestBtn1 在水平和垂直两个方向上,都自动拉伸填满父布局的可用空间。
TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn1.setMinimumSize(160,30); //设置按钮最小长度和高度
TestBtn2.setText("TestBtn2");
TestBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn2.setMinimumSize(160,30);
hlayout1->setSpacing(10);
hlayout1->addWidget(&TestBtn1);
hlayout1->addWidget(&TestBtn2);
TestBtn3.setText("TestBtn3");
TestBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn3.setMinimumSize(160,30);
TestBtn4.setText("TestBtn4");
TestBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn4.setMinimumSize(160,30);
hlayout2->setSpacing(10);
hlayout2->addWidget(&TestBtn3);
hlayout2->addWidget(&TestBtn4);
vlayout->setSpacing(10); //设置按钮之间的距离
vlayout->addLayout(hlayout1);
vlayout->addLayout(hlayout2);
setLayout(vlayout);
}
4.布局管理器中的比例系数
-
默认情况下以等比例的方式更新组件的大小
-
可以自定义组件大小更新时的比例系数
void Widget::testVBoxLayout()
{
QVBoxLayout* layout = new QVBoxLayout();TestBtn1.setText("TestBtn1"); //让按钮 TestBtn1 在水平和垂直两个方向上,都自动拉伸填满父布局的可用空间。 TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); TestBtn1.setMinimumSize(160,30); //设置按钮最小长度和高度 TestBtn2.setText("TestBtn2"); TestBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); TestBtn2.setMinimumSize(160,30); TestBtn3.setText("TestBtn3"); TestBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); TestBtn3.setMinimumSize(160,30); TestBtn4.setText("TestBtn4"); TestBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); TestBtn4.setMinimumSize(160,30); layout->setSpacing(30); //设置按钮之间的距离 layout->addWidget(&TestBtn1); layout->addWidget(&TestBtn2); layout->addWidget(&TestBtn3); layout->addWidget(&TestBtn4); layout->setStretch(0, 1); //定义第0个格子的比例系数是1 layout->setStretch(1, 1); layout->setStretch(2, 2); layout->setStretch(3, 2); setLayout(layout);}
void Widget::testHBoxLayout()
{
QHBoxLayout* layout = new QHBoxLayout();TestBtn1.setText("TestBtn1"); //让按钮 TestBtn1 在水平和垂直两个方向上,都自动拉伸填满父布局的可用空间。 TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); TestBtn1.setMinimumSize(160,30); //设置按钮最小长度和高度 TestBtn2.setText("TestBtn2"); TestBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); TestBtn2.setMinimumSize(160,30); TestBtn3.setText("TestBtn3"); TestBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); TestBtn3.setMinimumSize(160,30); TestBtn4.setText("TestBtn4"); TestBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); TestBtn4.setMinimumSize(160,30); layout->setSpacing(30); //设置按钮之间的距离 layout->addWidget(&TestBtn1); layout->addWidget(&TestBtn2); layout->addWidget(&TestBtn3); layout->addWidget(&TestBtn4); layout->setStretchFactor(&TestBtn1, 1); //将TestBtn1设置系数为1 layout->setStretchFactor(&TestBtn2, 2); layout->setStretchFactor(&TestBtn3, 1); layout->setStretchFactor(&TestBtn4, 3); setLayout(layout);}
注意:组件的初始大小是独立于布局管理器设置的,因此不能保证组件的大小始终符合比例系数的设置,例如上述代码中设置了按钮的初始大小,所以一开始的时候,比例对应不是设置的系数
5.QGridLayout布局管理器,以网格(二维矩阵)的方式管理界面组件
void Widget::testGridLayout1()
{
QGridLayout* layout = new QGridLayout();
TestBtn1.setText("TestBtn1");
//让按钮 TestBtn1 在水平和垂直两个方向上,都自动拉伸填满父布局的可用空间。
TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn1.setMinimumSize(160,30); //设置按钮最小长度和高度
TestBtn2.setText("TestBtn2");
TestBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn2.setMinimumSize(160,30);
TestBtn3.setText("TestBtn3");
TestBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn3.setMinimumSize(160,30);
TestBtn4.setText("TestBtn4");
TestBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn4.setMinimumSize(160,30);
layout->setSpacing(10);
layout->addWidget(&TestBtn1, 0, 0); //将TestBtn1按钮放在(0,0)位置
layout->addWidget(&TestBtn2, 0, 1);
layout->addWidget(&TestBtn3, 1, 0);
layout->addWidget(&TestBtn4, 1, 1);
layout->setRowStretch(0, 1); //设置第0行的比例因子为1
layout->setRowStretch(1, 3);
layout->setColumnStretch(0, 1); //设置第0列的比例因子为1
layout->setColumnStretch(1, 3);
setLayout(layout);
}
void Widget::testGridLayout2()
{
QGridLayout* layout = new QGridLayout();
TestBtn1.setText("TestBtn1");
//让按钮 TestBtn1 在水平和垂直两个方向上,都自动拉伸填满父布局的可用空间。
TestBtn1.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn1.setMinimumSize(160,30); //设置按钮最小长度和高度
TestBtn2.setText("TestBtn2");
TestBtn2.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn2.setMinimumSize(160,30);
TestBtn3.setText("TestBtn3");
TestBtn3.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn3.setMinimumSize(160,30);
TestBtn4.setText("TestBtn4");
TestBtn4.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
TestBtn4.setMinimumSize(160,30);
layout->setSpacing(10);
layout->addWidget(&TestBtn1, 0, 0, 2, 1); //将TestBtn1按钮放在(0,0)位置,并且占用2行1列
layout->addWidget(&TestBtn2, 0, 1, 2, 1);
layout->addWidget(&TestBtn3, 2, 0, 1, 2);
layout->addWidget(&TestBtn4, 3, 0, 1, 2);
\
setLayout(layout);
}