布局管理器
- 1. 布局管理器
- 2. QVBoxLayout——垂直布局
- 3. QHBoxLayout——水平布局
- 4. QGridLayout——网格布局
- 5. QFormLayout——表单布局
- 6. QSpacer
1. 布局管理器
在我们之前值ui界面进行拖拽设置控件时,都是通过手动的控制控件的位置的。同时每个控件的位置都是要计算坐标,最终通过setGeometry或者move方法来进行摆放的,这种设定方式其实并不方便.尤其是界面如果内容比较多的时候,不好计算.而且⼀个窗口大小往往是可以调整的,按照绝对定位的方式,也无法自适应窗口大小,因此Qt引入了布局管理器“LayOut"机制
2. QVBoxLayout——垂直布局
核心属性:
属性 | 说明 |
---|---|
layoutLeftMargin | 左侧边距 |
layoutRightMargin | 右侧边距 |
layoutTopMargin | 上方边距 |
layoutBottomMargin | 下方边距 |
layoutSpacing | 相邻元素之间的间距 |
代码样例:
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 创建三个按钮QPushButton* but1 = new QPushButton("按钮一");QPushButton* but2 = new QPushButton("按钮二");QPushButton* but3 = new QPushButton("按钮三");// 创建布局管理器,并把三个按钮添加到里面QVBoxLayout* layout = new QVBoxLayout();layout->addWidget(but1);layout->addWidget(but2);layout->addWidget(but3);// 将布局管理器不知道widget中this->setLayout(layout);
}
运行程序,可以看到此时界面上的按钮就存在于布局管理器中.随着窗口尺寸变化二发发改变.此时三个按钮的尺寸和位置,都是自动计算出来的.
通过上述代码的方式,只能给这个widget设定⼀个布局管理器.实际上也可以通过Qt Design在⼀个窗口中创建多个布局管理器.
但是当我们运行起来的时候,我们会发现当我们改变窗口大小的时候,这个布局管理器的大小并不会发生改变。这其实是因为我们使用Qt Designer创建布局管理器的时候其实实现创建了一个Widget,设置了geometry属性后才把这个layout设置到widget中,二实际上一个widget只能包含一个layout
3. QHBoxLayout——水平布局
二QHBoxLayout其实和QVBoxLayout属性是一致的,用法也是一致的。
属性 | 说明 |
---|---|
layoutLeftMargin | 左侧边距 |
layoutRightMargin | 右侧边距 |
layoutTopMargin | 上方边距 |
layoutBottomMargin | 下方边距 |
layoutSpacing | 相邻元素之间的间距 |
代码样例1:
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 创建三个按钮QPushButton* but1 = new QPushButton("按钮一");QPushButton* but2 = new QPushButton("按钮二");QPushButton* but3 = new QPushButton("按钮三");// 创建布局管理器,并把三个按钮添加到里面QHBoxLayout* layout = new QHBoxLayout();layout->addWidget(but1);layout->addWidget(but2);layout->addWidget(but3);// 将布局管理器不知道widget中this->setLayout(layout);
}
代码样例2:也可以支持嵌套布局
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* but1 = new QPushButton("but1");QPushButton* but2 = new QPushButton("but2");QVBoxLayout* vlayout = new QVBoxLayout();vlayout->addWidget(but1);vlayout->addWidget(but2);this->setLayout(vlayout);QPushButton* but3 = new QPushButton("but3");QPushButton* but4 = new QPushButton("but4");QHBoxLayout* hlayout = new QHBoxLayout();hlayout->addWidget(but3);hlayout->addWidget(but4);vlayout->addLayout(hlayout);
}
4. QGridLayout——网格布局
QGridLayout和QVBoxLayout,QHBoxLayout的用法相似,只不过QGridLayout是有行列的。
核心属性:
属性 | 说明 |
---|---|
layoutLeftMargin | 左侧边距 |
layoutRightMargin | 右侧边距 |
layoutTopMargin | 上方边距 |
layoutBottomMargin | 下方边距 |
layoutHorizontalSpacing | 相邻元素之间水平方向的间距 |
layoutVerticalSpacing | 相邻元素之间垂直方向的间距 |
layoutRowStretch | 行方向的拉伸系数 |
layoutColumnStretch | 列方向的拉伸系数 |
代码样例:
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QPushButton* but1 = new QPushButton("but1");QPushButton* but2 = new QPushButton("but2");QPushButton* but3 = new QPushButton("but3");QGridLayout* layout = new QGridLayout();layout->addWidget(but1, 0, 0);layout->addWidget(but2, 1, 1);layout->addWidget(but3, 2, 2);this->setLayout(layout);
}
我们也可以对布局进行设置拉伸系数,也就是按一定的比例进行布局。
代码样例:水平方向设置拉伸系数
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 创建 6 个按钮QPushButton* btn1 = new QPushButton("按钮1");QPushButton* btn2 = new QPushButton("按钮2");QPushButton* btn3 = new QPushButton("按钮3");QPushButton* btn4 = new QPushButton("按钮4");QPushButton* btn5 = new QPushButton("按钮5");QPushButton* btn6 = new QPushButton("按钮6");// 创建⽹格布局管理器, 并且添加元素QGridLayout* layout = new QGridLayout();layout->addWidget(btn1, 0, 0);layout->addWidget(btn2, 0, 1);layout->addWidget(btn3, 0, 2);layout->addWidget(btn4, 1, 0);layout->addWidget(btn5, 1, 1);layout->addWidget(btn6, 1, 2);// 设置拉伸⽐例// 第 0 列拉伸⽐例设为 1;layout->setColumnStretch(0, 1);// 第 1 列拉伸⽐例设为 0, 即为固定⼤⼩, 不参与拉伸layout->setColumnStretch(1, 0);// 第 2 列拉伸⽐例设为 3, 即为第 2 列的宽度是第 0 列的 3 倍layout->setColumnStretch(2, 3);// 设置 layout 到窗⼝中.this->setLayout(layout);}
另外,QGridLayout 也提供了setRowStretch 设置行之间的拉伸系数.上述案例中,直接设置setRowStretch 效果不明显,因为每个按钮的高度是固定的.需要把按钮的垂直方向的sizePolicy 属性设置为QSizePolicy::Expanding 尽可能填充满布局管理器,才能看到效果.
使用setSizePolicy 设置按钮的尺寸策略. 可选的值如下:
- QSizePolicy::Ignored : 忽略控件的尺寸,不对布局产生影响。
- QSizePolicy::Minimum :控件的最小尺寸为固定值,布局时不会超过该值。
- QSizePolicy::Maximum :控件的最大尺寸为固定值,布局时不会小于该值。
- QSizePolicy::Preferred :控件的理想尺寸为固定值,布局时会尽量接近该值。
- QSizePolicy::Expanding :控件的尺寸可以根据空间调整,尽可能占据更多空间
- QSizePolicy::Shrinking :控件的尺寸可以根据空间调整,尽可能缩小以适应空间。
代码样例:处置方向上设置拉伸系数
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 创建 6 个按钮QPushButton* btn1 = new QPushButton("按钮1");QPushButton* btn2 = new QPushButton("按钮2");QPushButton* btn3 = new QPushButton("按钮3");QPushButton* btn4 = new QPushButton("按钮4");QPushButton* btn5 = new QPushButton("按钮5");QPushButton* btn6 = new QPushButton("按钮6");// 设置按钮的 sizePolicy, 此时按钮的⽔平⽅向和垂直⽅向都会尽量舒展开btn1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);btn2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);btn3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);btn4->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);btn5->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);btn6->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);// 创建⽹格布局管理器, 并且添加元素QGridLayout* layout = new QGridLayout();layout->addWidget(btn1, 0, 0);layout->addWidget(btn2, 0, 1);layout->addWidget(btn3, 1, 0);layout->addWidget(btn4, 1, 1);layout->addWidget(btn5, 2, 0);layout->addWidget(btn6, 2, 1);// 设置拉伸⽐例// 第 0 ⾏拉伸⽐例设为 1;layout->setRowStretch(0, 1);// 第 1 ⾏拉伸⽐例设为 0, 即为固定⼤⼩, 不参与拉伸layout->setRowStretch(1, 0);// 第 2 ⾏拉伸⽐例设为 3, 即为第 2 ⾏的宽度是第 0 ⾏的 3 倍layout->setRowStretch(2, 3);// 设置 layout 到窗⼝中.this->setLayout(layout);
}
5. QFormLayout——表单布局
QRormLayout表单布局,多用于给手机用户的信息,比如我们在学校里,qq群里会发收集每个人的电话号码的文档,其中这个文档中要输入学号,姓名,和电话,填完之后就可以直接进行提交了。
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);// 创建 layoutQFormLayout* layout = new QFormLayout();this->setLayout(layout);// 创建三个 labelQLabel* label1 = new QLabel("姓名");QLabel* label2 = new QLabel("学号");QLabel* label3 = new QLabel("电话");// 创建三个 lineEditQLineEdit* lineEdit1 = new QLineEdit();QLineEdit* lineEdit2 = new QLineEdit();QLineEdit* lineEdit3 = new QLineEdit();// 创建⼀个提交按钮QPushButton* btn = new QPushButton("提交");// 把上述元素添加到 layout 中layout->addRow(label1, lineEdit1);layout->addRow(label2, lineEdit2);layout->addRow(label3, lineEdit3);layout->addRow(NULL, btn);
}
6. QSpacer
上述我们设置的布局中的按钮之间挨着都是比较近的,有的时候我们想要他们之间有些间隔,就可以用到QSapcer
核心属性:
属性 | 说明 |
---|---|
width | 宽度 |
height | 高度 |
hData | 水平方向的 sizePolicy (QSizePolicy::Ignored : 忽略控件的尺寸,不对布局产⽣影响)(QSizePolicy::Minimum :控件的最小尺寸为固定值,布局时不会超过该值。)(QSizePolicy::Maximum : 控件的最大尺寸为固定值,布局时不会小于该值。 )(QSizePolicy::Preferred : 控件的理想尺寸为固定值,布局时会尽量接近该值。)(QSizePolicy::Expanding : 控件的尺寸可以根据空间调整,尽可能占据更多空间。)(QSizePolicy::Shrinking : 控件的尺寸可以根据空间调整,尽可能缩小以适应空间。) |
vData | 垂直方向的 sizePolicy 选项同上. |
Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);QHBoxLayout* layout = new QHBoxLayout();this->setLayout(layout);QPushButton* btn1 = new QPushButton("按钮1");QPushButton* btn2 = new QPushButton("按钮2");// 创建SpacerQSpacerItem* spacer = new QSpacerItem(200, 20);layout->addWidget(btn1);// 这个是按照添加的顺序来添加的,放在中间说明放在两个按钮的中间layout->addSpacerItem(spacer);layout->addWidget(btn2);
}