C++客户端Qt开发——常用控件(布局管理器)

avatar
作者
猴君
阅读量:2

7.布局管理器

之前使用Qt在界面上创建的控件,都是通过"绝对定位"的方式来设定的

也就是每个控件所在的位置,都需要计算坐标,最终通过setGeometry或者

move方式摆放过去,

这种设定方式其实并不方便,尤其是界面如果内容比较多,不好计算,而且一个窗口大小往往是可以调整的,按照绝对定位的方式,也无法自适应窗口大小

因此Qt引入"布局管理器"(Layout)机制,来解决上述问题.

布局管理器并非Qt独有.其他的GUI开发框架,像Android,前端等也有类似的机制

①垂直布局

使用QVBoxLayout表示垂直的布局管理器,V是vertical的缩写

属性

说明

layoutLeftMargin

左侧边距

layoutRightMargin

右侧边距

layoutTopMargin

上方边距

layoutBottomMargin

下方边距

layoutSpacing

相邻元素之间的间距

Layout只是用于界面布局,并没有提供信号,

①使用QVBoxLayout管理多个控件

#include "widget.h" #include "ui_widget.h" #include<QPushButton> #include<QVBoxLayout>  Widget::Widget(QWidget *parent)     : QWidget(parent)     , ui(new Ui::Widget) {     ui->setupUi(this);      QPushButton* btn1 = new QPushButton("按钮1");     QPushButton* btn2 = new QPushButton("按钮2");     QPushButton* btn3 = new QPushButton("按钮3");      //创建布局管理器,并把按钮添加进去     //如果创建的时候指定父元素为this,则后面不需要setLayout方法了     QVBoxLayout* layout = new QVBoxLayout();     layout->addWidget(btn1);     layout->addWidget(btn2);     layout->addWidget(btn3);      //把布局管理器设置到Widget中     this->setLayout(layout);  }  Widget::~Widget() {     delete ui; }  

②创建两个QVBoxLayout

按钮已经自动排列好,只不过当前这些按钮的位置不能随着窗口大小自动变化

通过Qt Designer创建的布局管理器,其实是先创建了一个widget,.设置过geometry属性的,再把这个layout设置到这个widget

实际上,一个widget只能包含一个layout

打开ui文件的原始ml,可以看到其中的端倪

这种情况下layout并非是窗口widget的布局管理器,因此不会随着窗口大小改变

②水平布局

使用QHBox Layout,表示垂直的布局管理器.H是horizontal的缩写

核心属性(和QVBoxLayout属性是一致的)

属性

说明

layoutLeftMargin

左侧边距

layoutRightMargin

右侧边距

layoutTopMargin

上方边距

layoutBottomMargin

下方边距

layoutSpacing

相邻元素之间的间距

①使用QHBoxLayout管理控件

#include "widget.h" #include "ui_widget.h" #include<QPushButton> #include<QHBoxLayout>  Widget::Widget(QWidget *parent)     : QWidget(parent)     , ui(new Ui::Widget) {     ui->setupUi(this);      //创建三个按钮,并且把按钮添加到布局控制器中     QPushButton* btn1 = new QPushButton("按钮1");     QPushButton* btn2 = new QPushButton("按钮2");     QPushButton* btn3 = new QPushButton("按钮3");      //创建布局管理器     QHBoxLayout* layout = new QHBoxLayout();     layout->addWidget(btn1);     layout->addWidget(btn2);     layout->addWidget(btn3);      this->setLayout(layout);  }  Widget::~Widget() {     delete ui; }  

②嵌套下的layout

Layout里面可以再嵌套上其他的layout,从而达到更复杂的布局效果

#include "widget.h" #include "ui_widget.h" #include<QVBoxLayout> #include<QHBoxLayout> #include<QPushButton>  Widget::Widget(QWidget *parent)     : QWidget(parent)     , ui(new Ui::Widget) {     ui->setupUi(this);      //创建顶层layout     QVBoxLayout* layoutParent = new QVBoxLayout();     this->setLayout(layoutParent);      //添加两个按钮进去     QPushButton* btn1 = new QPushButton("按钮1");     QPushButton* btn2 = new QPushButton("按钮2");      layoutParent->addWidget(btn1);     layoutParent->addWidget(btn2);      //创建子layout      QHBoxLayout* layoutChild = new QHBoxLayout();      //添加两个按钮进去     QPushButton* btn3 = new QPushButton("按钮3");     QPushButton* btn4 = new QPushButton("按钮4");      layoutChild->addWidget(btn3);     layoutChild->addWidget(btn4);      //把子layout添加到父layout中     layoutParent->addLayout(layoutChild); }  Widget::~Widget() {     delete ui; }  

③网格布局

Qt中还提供了QGridLayout用来实现网格布局的效果.可以达到M*N的这种网格的效果

核心属性

整体和QVBoxLayout以及QHBoxLayout相似,但是设置spacing的时候是按照垂直水平两个方向来设置的

属性

说明

layoutLeftMargin

左侧边距

layoutRightMargin

右侧边距

layoutTopMargin

上方边距

layoutBottomMargin

下方边距

layoutHorizontalSpacing

相邻元素之间水平方向的间距

layoutVerticalSpacing

相邻元素之间垂直方向的间距

layoutRowStretch

行方向的拉伸系数

layoutColumnStretch

列方向的拉伸系数

①使用QGridLayout管理元素

#include "widget.h" #include "ui_widget.h" #include<QPushButton> #include<QGridLayout>  Widget::Widget(QWidget *parent)     : QWidget(parent)     , ui(new Ui::Widget) {     ui->setupUi(this);      //创建四个按钮     QPushButton* btn1 = new QPushButton("按钮1");     QPushButton* btn2 = new QPushButton("按钮2");     QPushButton* btn3 = new QPushButton("按钮3");     QPushButton* btn4 = new QPushButton("按钮4");      //创建网格布局管理器,并添加元素     QGridLayout* layout = new QGridLayout();     layout->addWidget(btn1,0,0);     layout->addWidget(btn2,0,1);     layout->addWidget(btn3,1,0);     layout->addWidget(btn4,1,1);      this->setLayout(layout); }  Widget::~Widget() {     delete ui; }  

//假如是这种布局 //相当于QHBoxLayout layout->addWidget(btn1,0,1); layout->addWidget(btn2,0,2); layout->addWidget(btn3,0,3); layout->addWidget(btn4,0,4); //假如是这种布局 //相当于QVBoxLayout layout->addWidget(btn1, 1, 0); layout->addWidget(btn2, 2, 0); layout->addWidget(btn3, 3, 0); layout->addWidget(btn4, 4, 0);

此处也要注意,设置行和列的时候,如果设置的是一个很大的值,但是这个值和上一个值之间并没有其他的元素,那么并不会在中间腾出额外的空间

假如把btn4设置在第10行,但是由于3-9行没有元素.因此btn4仍然会紧挨在btn3下方,看起来和上面的0 1 2 3的情况是相同的

②设置QGridLayout中元素的大小比例

#include "widget.h" #include "ui_widget.h" #include<QPushButton> #include<QGridLayout>  Widget::Widget(QWidget *parent)     : QWidget(parent)     , ui(new Ui::Widget) {     ui->setupUi(this);      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);      this->setLayout(layout); }  Widget::~Widget() {     delete ui; }  

另外,QGridLayout也提供了setRowStretch设置行之间的拉伸系数

上述案例中,直接设置setRowStretch效果不明显,因为每个按钮的高度是固定的.需要把按钮的垂直方向的sizePolicy属性设置为QSizePolicy::Expanding尽可能填充满布局管理器,才能看到效果

③设置垂直方向的拉伸系数

#include "widget.h" #include "ui_widget.h" #include<QPushButton> #include<QGridLayout>  Widget::Widget(QWidget *parent)     : QWidget(parent)     , ui(new Ui::Widget) {     ui->setupUi(this);      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");      //设置按钮的sizePolice,此时按钮的水平和垂直方向都会尽量舒展开     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);      this->setLayout(layout);  }  Widget::~Widget() {     delete ui; }  

④表单布局

除了上述的布局管理器之外,Qt还提供了QFormLayout,属于是QGridLayout的特殊情况,专门用于实现两列表单的布局

这种表单布局多用于让用户填写信息的场景.左侧列为提示,右侧列为输入框

#include "widget.h" #include "ui_widget.h" #include<QFormLayout> #include<QLabel> #include<QLineEdit> #include<QPushButton>  Widget::Widget(QWidget *parent)     : QWidget(parent)     , ui(new Ui::Widget) {     ui->setupUi(this);      QFormLayout* layout = new QFormLayout();     this->setLayout(layout);      //创建三个label     QLabel* label1 = new QLabel("姓名");     QLabel* label2 = new QLabel("年龄");     QLabel* label3 = new QLabel("电话");      //创建三个lineEdit     QLineEdit* 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);  }  Widget::~Widget() {     delete ui; }  

⑤Spacer 在控件之间添加一段空白

属性

说明

width

宽度

height

高度

hData

水平方向的sizePolicy

QSizePolicy::Ignored:忽略控件的尺寸,不对布局产生影响。

QSizePolicy::Minimum:控件的最小尺寸为固定值,布局时不会超过该值。

QSizePolicy:Maximum:控件的最大尺寸为固定值,布局时不会小于该值。

QSizePolicy::Preferred:控件的理想尺寸为固定值,布局时会尽量接近该值。

QSizePolicy::Expanding:控件的尺寸可以根据空间调整,尽可能占据更多空间。

QSizePolicy::Shrinking:控件的尺寸可以根据空间调整,尽可能缩小以适应空间。

vData

垂直方向的sizePolicy

选项同上

①创建一组左右排列的按钮

#include "widget.h" #include "ui_widget.h" #include<QVBoxLayout> #include<QPushButton>  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");      //创建Spacer     QSpacerItem* spacer = new QSpacerItem(200,20);      layout->addWidget(btn1);      //在两个Widget中间件加上空白     layout->addSpacerItem(spacer);      layout->addWidget(btn2); }  Widget::~Widget() {     delete ui; }  

调整QSpacerltem不同的尺寸,即可看到不同的间距

Qt Designer中,也可以直接给界面上添加spacer

广告一刻

为您即时展示最新活动产品广告消息,让您随时掌握产品活动新动态!