当前位置: 代码迷 >> 综合 >> 11.QT-布局管理器(Box,Grid,Form,Stacked)
  详细解决方案

11.QT-布局管理器(Box,Grid,Form,Stacked)

热度:20   发布时间:2023-12-03 06:51:06.0

布局管理器简介

  • QT中提供了对界面组件进行布局管理的类,用于对界面组件进行管理,
  • 能够自动排列窗口中的界面组件
  • 窗口大小变化后,便会自动更新界面组件的大小。
  • 布局管理器可以自定义,从而达到更加个性化界面布局的效果
  • 布局管理器可以相互嵌套,完成所有常用的界面布局
  • QLayout是Qt中布局管理器的抽象基类,只能使用它的子类,如下图所示:

QBoxLayout水平/垂直布局

QBoxLayout有两个子类:QHBoxLayout(水平)和QVBoxLayout(垂直)

垂直布局,表示将垂直方向分为一个个格子,如下图所示:

 水平布局如下图所示:

QVBoxLayout使用

int main(int argc, char *argv[])
{QApplication a(argc, argv);QWidget w;QVBoxLayout *layout=new QVBoxLayout;QPushButton btn1("test1",&w);QPushButton btn2("test2",&w);QPushButton btn3("test3",&w);btn1.setMaximumSize(600,360);btn1.setMinimumSize(100,60);btn2.setMaximumSize(600,360);btn2.setMinimumSize(100,60);btn3.setMaximumSize(600,360);btn3.setMinimumSize(100,60);layout->addWidget(&btn1);       //向布局管理器添加组件,实现自动布局layout->addWidget(&btn2);layout->addWidget(&btn3);w.setLayout(layout);           //为部件设置布局管理器layout->setSpacing(10);w.show();return a.exec();
}

QHBoxLayout使用 

int main(int argc, char *argv[])
{QApplication a(argc, argv);QWidget w;QHBoxLayout *layout=new QHBoxLayout;QPushButton btn1("test1",&w);QPushButton btn2("test2",&w);QPushButton btn3("test3",&w);btn1.setMaximumSize(600,360);btn1.setMinimumSize(100,60);btn2.setMaximumSize(600,360);btn2.setMinimumSize(100,60);btn3.setMaximumSize(600,360);btn3.setMinimumSize(100,60);layout->addWidget(&btn1);       //向布局管理器添加组件,实现自动布局layout->addWidget(&btn2);layout->addWidget(&btn3);w.setLayout(layout);           //为部件设置布局管理器layout->setSpacing(10);w.show();return a.exec();
}

QBoxLayout相互嵌套

之前,我们写了QHBoxLayout(水平)和QVBoxLayout(垂直),但是只是单方面自动布局.

其实任何BoxLayout都可以相互嵌套,比如水平+垂直布局,本质就是一个QGridLayout(后面会讲)

示例代码如下:

#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);QHBoxLayout *Hlayout1=new QHBoxLayout;QHBoxLayout *Hlayout2=new QHBoxLayout;QVBoxLayout *Vlayout=new QVBoxLayout;QWidget w;QPushButton btn1("test1",&w);QPushButton btn2("test2",&w);QPushButton btn3("test3",&w);QPushButton btn4("test4",&w);btn1.setMaximumSize(600,360);btn1.setMinimumSize(100,60);btn2.setMaximumSize(600,360);btn2.setMinimumSize(100,60);btn3.setMaximumSize(600,360);btn3.setMinimumSize(100,60);btn4.setMaximumSize(600,360);btn4.setMinimumSize(100,60);Hlayout1->addWidget(&btn1);       //水平布局: btn1  btn2Hlayout1->addWidget(&btn2);Hlayout1->setSpacing(10);Hlayout2->addWidget(&btn3);      //水平布局: btn3  btn4Hlayout2->addWidget(&btn4);Hlayout2->setSpacing(10);Vlayout->addLayout(Hlayout1);     //垂直布局: Hlayout1 Hlayout2Vlayout->addLayout(Hlayout2);Vlayout->setSpacing(10);w.setLayout(Vlayout);           //设置布局管理器,由于Vlayout管理着Hlayout1 Hlayout2,所以只填写一个即可w.show();return a.exec();
}

 效果如下所示:

布局管理器比例系数

默认情况下,组件之间以等比例的方式改变组件大小.

其实用户也可以自定义组件之间比例系数,当窗口放大时,便来更新比例系数.

常用函数:

QBoxLayout::setStretch ( int index, int stretch );     //设置具体组件的拉伸系数
// index:表示布局管理器里的第几个组件
// stretch :拉伸系数bool  QBoxLayout::setStretchFactor ( QWidget * widget, int stretch );//设置部件拉伸系数,如果存在*widget这个组件,则设置成功,返回true
bool QBoxLayout::setStretchFactor ( QLayout * layout, int stretch );//设置布局拉伸系数, ,如果存在*layout这个组件,则设置成功,返回true

示例代码如下:

#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QPushButton>
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);QHBoxLayout *Hlayout1=new QHBoxLayout;QHBoxLayout *Hlayout2=new QHBoxLayout;QVBoxLayout *Vlayout=new QVBoxLayout;QWidget w;QPushButton btn1("test1",&w);QPushButton btn2("test2",&w);QPushButton btn3("test3",&w);QPushButton btn4("test4",&w);btn1.setMaximumSize(600,360);btn1.setMinimumSize(100,60);btn2.setMaximumSize(600,360);btn2.setMinimumSize(100,60);btn3.setMaximumSize(600,360);btn3.setMinimumSize(100,60);btn4.setMaximumSize(600,360);btn4.setMinimumSize(100,60);//设置大小策略,Expanding表示组件可扩展btn1.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);btn2.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);btn3.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);btn4.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);Hlayout1->addWidget(&btn1);       //水平布局: btn1  btn2Hlayout1->addWidget(&btn2);Hlayout1->setSpacing(10);Hlayout2->addWidget(&btn3);      //水平布局: btn3  btn4Hlayout2->addWidget(&btn4);Hlayout2->setSpacing(10);Vlayout->addLayout(Hlayout1);     //垂直布局: Hlayout1 Hlayout2Vlayout->addLayout(Hlayout2);Vlayout->setStretchFactor(Hlayout1,1);Vlayout->setStretchFactor(Hlayout2,3);Vlayout->setSpacing(10);w.setLayout(Vlayout);           //设置布局管理器,由于Vlayout管理着Hlayout1 Hlayout2,所以只填写一个即可w.show();return a.exec();
}

拉伸窗口后:

QGridLayout网格布局

以网格的方式管理界面组件,类似于:上面嵌套方式来使用QBoxLayout.

常用函数:

void  addWidget ( QWidget * widget, int row, int column, Qt::Alignment alignment = 0 );// row  column :表示将widget这个部件放在网格哪个位置void  addWidget ( QWidget * widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment = 0 );// row  column :表示将widget这个部件放在网格哪个位置// rowSpan: widget这个部件占多少行// columnSpan: widget这个部件占多少列void setColumnStretch(int column,int stretch);          //设置列拉伸系数// column:设置布局管理器里的第几列,第1列为0void setRowStretch(int row,int stretch);               //设置行拉伸系数// row:设置的第几行 

示例代码:

#include <QGridLayout>
#include <QPushButton>
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);QGridLayout *layout=new QGridLayout;QWidget w;QPushButton btn1("test1",&w);QPushButton btn2("test2",&w);QPushButton btn3("test3",&w);QPushButton btn4("test4",&w);btn1.setMinimumSize(100,60);btn2.setMinimumSize(100,60);btn3.setMinimumSize(100,60);btn4.setMinimumSize(100,60);//设置大小策略,Expanding表示组件可扩展btn1.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);btn2.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);btn3.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);btn4.setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);layout->addWidget(&btn1,0,0);layout->addWidget(&btn2,0,1);layout->addWidget(&btn3,1,0);layout->addWidget(&btn4,1,1);layout->setRowStretch(0,1);        //设置第0行,比例为1layout->setRowStretch(1,2);        //设置第1行,比例为2layout->setColumnStretch(0,1);     //设置第0列,比例为1layout->setColumnStretch(1,2);     //设置第1列,比例为2w.setLayout(layout);               //设置布局管理器w.show();return a.exec();
}

拉伸窗口后:

QGridLayout相互嵌套

之前讲过任何BoxLayout都可以相互嵌套,所以QGridLayout也支持布局管理器嵌套,比如QGridLayout+ QVBoxLayout嵌套:

int main(int argc, char *argv[])
{QApplication a(argc, argv);QGridLayout *layout=new QGridLayout;QVBoxLayout *Vlyt=new QVBoxLayout;QWidget w;QPushButton btn1("test1",&w);QPushButton btn2("test2",&w);QPushButton btn3("test3",&w);QPushButton btn4("test4",&w);QPushButton btn5("test5",&w);btn1.setMinimumSize(100,60);btn2.setMinimumSize(100,60);btn3.setMinimumSize(100,60);btn4.setMinimumSize(100,30);        //btn4 btn5按钮需要缩小高度btn5.setMinimumSize(100,30);//设置大小策略,Expanding表示组件可扩展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);Vlyt->addWidget(&btn4);Vlyt->addWidget(&btn5);layout->addWidget(&btn1,0,0);layout->addWidget(&btn2,0,1);layout->addWidget(&btn3,1,0);layout->addLayout(Vlyt,1,1);layout->setRowStretch(0,1);        //设置第0行,比例为1layout->setRowStretch(1,2);        //设置第1行,比例为2layout->setColumnStretch(0,1);     //设置第0列,比例为1layout->setColumnStretch(1,2);     //设置第1列,比例为2w.setLayout(layout);              //设置布局管理器w.show();return a.exec();
}

拉伸窗口后:

QFormLayout表单布局

以表单的方式管理界面组件,专为标签字段(组件)的形式创建的

表单布局也支持嵌套,可以管理子布局

常用函数:

addRow ( QWidget * label, QWidget * field );
addRow ( QWidget * label, QLayout * field );
addRow ( const QString & labelText, QWidget * field );
addRow ( const QString & labelText, QLayout * field );void setLabelAlignment ( Qt::Alignment alignment );//设置标签对齐方式,比如标签左对齐void  setRowWrapPolicy ( RowWrapPolicy policy );//设置字段包装策略//比如参数WrapLongRows:表示给标签足够长空间,如果一行满足不了标签和字段显示,则将字段放在下行显示//参数QFormLayout::WrapAllRows: 示字段信息总在标签下面列出(占据整个行大小)

示例代码:

#include <QLineEdit>
#include <QFormLayout>
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);QWidget w(0,Qt::WindowCloseButtonHint);QLineEdit line1(&w);QLineEdit line2(&w);QLineEdit line3(&w);QFormLayout *layout= new QFormLayout;layout->addRow("姓名:",&line1);layout->addRow("邮箱:",&line2);layout->addRow("地址:",&line3);layout->setRowWrapPolicy(QFormLayout::WrapAllRows); //设置字段总在标签下面w.setLayout(layout);w.show();return a.exec();
}

效果:

QStackedLayout栈式布局

  • 将所有组件进行垂直管理
  • 并且每次只能有一个组件现在在屏幕上 
  • 只有最顶层的组件才会被最终显示
  • 常用于图片播放,安装向导

特点

  • 组件大小一致且充满父组件的显示区
  • 能够自由切换需要显示的组件
  • 不能直接嵌套其它布局管理器,只能间接嵌套

常用函数:

int addWidget ( QWidget * widget );               //顺序添加组件int insertWidget ( int index, QWidget * widget );       //插入组件void removeWidget ( QWidget * widget );                 //删除组件QWidget * currentWidget() ;                            //返回当前组件int   currentIndex();                                  //返回当前组件索引值void setCurrentIndex ( int index );                    //切换当前组件void setCurrentWidget ( QWidget * widget );            //更换当前显示的组件

代码试验,实现按钮切换页效果

Widget.h

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QPushButton>
#include <QStackedLayout>class Widget : public QWidget
{Q_OBJECTQStackedLayout *stack;QPushButton btn1;QPushButton btn2;QPushButton btn3;public:Widget(QWidget *parent = nullptr);~Widget();protected slots:void onBtn();
};
#endif // WIDGET_H

Widget.cpp

#include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent),btn1("第一页",this),btn2("第二页",this),btn3("第三页",this)
{btn1.setFixedSize(100,38);btn2.setFixedSize(100,38);btn3.setFixedSize(100,38);QHBoxLayout *Hlyt = new QHBoxLayout;QVBoxLayout *Vlyt = new QVBoxLayout;QSpacerItem *vSpacer = new QSpacerItem(100, 20, QSizePolicy::Minimum, QSizePolicy::Expanding);   // 使用了一个垂直弹簧Vlyt->addWidget(&btn1);Vlyt->addWidget(&btn2);Vlyt->addWidget(&btn3);Vlyt->addItem(vSpacer);Vlyt->setSpacing(5);stack = new QStackedLayout;QWidget *page1 = new QWidget(this);page1->setStyleSheet("background: rgb(255,0,0);");QWidget *page2 = new QWidget(this);page2->setStyleSheet("background: rgb(0,255,0);");QWidget *page3 = new QWidget(this);page3->setStyleSheet("background: rgb(0,0,255);");stack->addWidget(page1);stack->addWidget(page2);stack->addWidget(page3);Hlyt->addLayout(Vlyt);Hlyt->addLayout(stack);// 建立信号槽connect(&btn1, SIGNAL(clicked()), this, SLOT(onBtn()));connect(&btn2, SIGNAL(clicked()), this, SLOT(onBtn()));connect(&btn3, SIGNAL(clicked()), this, SLOT(onBtn()));this->setLayout(Hlyt);this->resize(700,500);
}void Widget::onBtn()
{QObject *obj =  this->sender();  // 获取信号发送者if (obj == &btn1) {stack->setCurrentIndex(0);} else if (obj == &btn2) {stack->setCurrentIndex(1);} else {stack->setCurrentIndex(2);}}Widget::~Widget()
{
}

main.cpp

#include "widget.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);Widget w;w.show();return a.exec();
}

效果:

Qml / Qt / C++技术交流群加 + 779866667 (本专栏文章相关源码免费,入群获取,并且不定时上传资源和文章源码)  

  相关解决方案