QT布局管理

x33g5p2x  于2021-12-17 转载在 其他  
字(8.6k)|赞(0)|评价(0)|浏览(375)

Qt提供了一组布局管理器,比如QLayout的几个子类,这里将它们称为布局管理器。

一张关系图看清楚关系:

布局管理系统

Qt包含了一组布局管理类,从而进行布局,比如QLayout的几个子类,这里将它们称为布局管理器。

所有QWidget的子类的实例都可以使用布局管理器管理位于它们之中的子部件,
QWidget::setLayout()函数可以在一个部件上应用布局管理器

它会完成以下几个任务:

本节内容可以在帮助索引中通过Layout Management关键字查看

1. 布局管理器

QLayout类是布局管理器的基类,是一个抽象基类,继承自QObject和QLayou-tItem类,
QLayoutItem类提供了一个供QLayout操作的抽象项目。
QLayout 和QLayoutItem都是在设计自己的布局管理器时才使用的,一般只需要使用QLayout的几个子类即可,它们分别是QBoxLayout(基本布局管理器)、QGridLayout(栅格布局管理器)、QFormLayout(窗体布局管理器)和QStackedLayout(栈布局管理器)。
这里QStackedLayout与第3章讲述的栈部件QStackedWidget用法相同,不再赘述。
转到那章

新建widget项目mylayout,类名MyWidget

ui拖入
Font Combo Box 字体选择框

Text Edit 文本编辑器

选择布局

最上边的工具栏—一个是水平布局,一个是垂直布局

点击主界面,点击垂直布局(crtl+L),来进行整体部件的垂直布局。

设置了顶层布局管理器(因为是对整个窗口设置的布局管理器,所以叫顶层布局管理器),可以.
看到两个部件已经填满了整个界面。

这时运行程序,然后拉伸窗口,两个部件会随着窗口的大小变化而变化,如图所示。这就是布局管理器的作用。

1. 基本布局管理器(QBoxLayout)

基本布局管理器QBoxLayout类可以使子部件在水平方向或者垂直方向排成一列。

它的两个子类QHBoxLayout水平布局管理器QVBoxLayout垂直布局管理器

下面打破已有的布局,使用代码实现水平布局。
先打破布局

或者

在widget构造函数中添加

//新建水平布局管理器
    QHBoxLayout *layout=new QHBoxLayout;
    //向布局管理器中添加部件
    layout->addWidget(ui->fontComboBox);
    layout->addWidget(ui->textEdit);
    //设置部件间的间隔
    layout->setSpacing(50);
    //设置布局管理器到边界的距离
    layout->setContentsMargins(0,0,50,100);//左,上,右,下

    setLayout(layout);//设为MyWidget的布局

也可以用insertwidget函数替代addwidget进行更精细的划分

layout->insertWidget(10,ui->fontComboBox,10,Qt::AlignHCenter);
     layout->insertWidget(20,ui->textEdit,20,Qt::AlignHCenter);

参考帮助文档:

然后垂直也与这个类似

2. 栅格布局管理器(QGridLayout)

使部件在网格中进行布局,它将所有的空间分割成一些行和列,行与列的交叉处形程了单元格,然后把部件放入一个确定的单元格

举个例子:
现在ui上拖入一个按钮

其实他在设计器中也是有的,可以直接使用

然后在mywidget中构造函数中:(把前面的水平管理布局先注释)

#include "mywidget.h"
#include "ui_mywidget.h"
#include <QHBoxLayout>
#include <QGridLayout>
#include <QPushButton>

MyWidget::MyWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MyWidget)
{
    ui->setupUi(this);
// //新建水平布局管理器
// QHBoxLayout *layout=new QHBoxLayout;
// //向布局管理器中添加部件
// layout->addWidget(ui->fontComboBox);
// layout->addWidget(ui->textEdit);
// layout->insertWidget(10,ui->fontComboBox,10,Qt::AlignHCenter);
// layout->insertWidget(20,ui->textEdit,20,Qt::AlignHCenter);
// //设置部件间的间隔
// layout->setSpacing(50);
// //设置布局管理器到边界的距离
// layout->setContentsMargins(0,0,50,100);//左,上,右,下

// setLayout(layout);//设为MyWidget的布局

    //新建按钮
    QPushButton *pushbutton =new QPushButton;
    pushbutton->setText("测试");
    pushbutton->setParent(this);//添加进去
    //或者这种新建 this添加进去
    QPushButton pushbutton1(this);
    pushbutton1.setText("nihao");

    //新建栅格布局管理器
    QGridLayout *layout=new QGridLayout;
   //添加部件,从第0行0列开始,占据1行2列
   layout->addWidget(ui->fontComboBox,0,0,1,2);
   //添加部件,从第0行2列开始,占据1行1列
   layout->addWidget(pushbutton,0,2,1,1);
   // 添加部件,从第1行0列开始,占据1行3列
    layout->addWidget(ui->textEdit, 1, 0, 1, 3);
     setLayout(layout);

}

MyWidget::~MyWidget()
{
    delete ui;
}

注意:
当部件加入到一个布局管理器中,然后将这个布局管理器再放到一个窗口部件上时,这个布局管理器以及它包含的所有部件都会自动重新定义自己的父对象(parent)为这个窗口部件,所以在创建布局管理器和其中的部件时并不用指定父部件。此外,也可以直接在设计模式时使用前面讲过的方法来使用栅格布局管理器。

3. 窗体布局管理器(QFormLayout)

用来管理表单的输入部件以及与它们相关的标签。
窗体布局管理器将它的子部件分为二列,左边是一些标签,右边是一些输入部件。
比如行编辑器或者数字选择框

下面用一个例子来看它与QGridLayout的不同之处

先将前面的代码注释掉,进入ui
拖入

双击或者右键添加窗口布局行

这里使用了QLineEdit行编辑器,当然也可以选择其他部件。填写的(&N)必须为英语半角的括号,表明它的快捷键为Alt+N。
设置伙伴关系,表示按下Alt+N时,光标自动跳转到标签后面对应的行编辑器中。单击"确定“键,则会在布局管理器中添加一个标签和一个行编辑器。

按照这种方法,再添加3行:
性别(&S),使用QComoBox
年龄(&A),使用QSpinBox;
邮箱(&M),使用QLineEdit。

完成后运行程序,
可以按下快捷键Alt+N,这样光标就可以定位到“姓名”标签后的行编辑器中。

可以在代码中使用addRow()函数来实现

//新建组件和表单管理器
   QLineEdit *nameEdit=new QLineEdit();
   QComboBox *xingbie=new QComboBox();
   QFormLayout *layout=new QFormLayout;
  layout->addRow("姓名:",nameEdit);
  layout->addRow("性别:",xingbie);
   //设置对齐
  layout->setLabelAlignment(Qt::AlignRight);//标签对齐
  layout->setFormAlignment(Qt::AlignLeft);//窗口
   setLayout(layout);

大概这样:

更详细的见: QT开发(二十一)——QT布局管理器
又遇见一个宝藏up,建议收藏它的系列课程

4. 综合使用布局管理器

前面讲到了3种布局管理器,真正使用时一般是将它们综合起来应用。现在将前面的界面再进行设计:按下Ctrl键的同时选中界面上的字体选择框fontComboBox和按钮pushButton,然后按下Ctrl+H快捷键将它们放人一个水平布局管理器中(其实也可以从部件栏中拖入一个Horizontal Layout,然后再将这两个部件放进去,效果是一样的)。然后再从部件栏中拖入一个Vertical Spacer垂直分隔符,用来在部件间产生,间隔,将它放在窗体布局管理器与水平布局管理器之间。最后单击主界面并按下Ctrl十L快捷键,让整个界面处于一个垂直布局管理器中。这时可以在右,上角的对象列表中选择分隔符Spacer,然后在属性栏中设置它的高度为100,如图4-3所示。这时运行程序可以看到,分隔符是不显示的。

这里综合使用了窗体布局管理器、水平布局管理器和垂直布局管理器,其中,垂直布局管理器是顶级布局管理器,因为它是主界面的布局,其他两个布局管理器都包含在它里面。如果要使用代码来实现将一一个子布局管理器放入一个父布局管理器之中,则可以使用父布局管理器的addLayout()函数。

这里举个例子:

/*上面的布局*/
//新建一个按钮
        QPushButton *pushbutton =new QPushButton;
        pushbutton->setText("测试");
        pushbutton->setParent(this);//添加进去

     //与字体框水平布局
      QHBoxLayout *layout1=new QHBoxLayout;
         //向布局管理器中添加部件
         layout1->addWidget(ui->fontComboBox);
         layout1->addWidget(pushbutton);
          layout1->insertWidget(10,ui->fontComboBox,10,Qt::AlignHCenter);
          layout1->insertWidget(20,pushbutton,20,Qt::AlignHCenter);
         //设置部件间的间隔
         layout1->setSpacing(50);
         //设置布局管理器到边界的距离
         layout1->setContentsMargins(0,0,50,100);//左,上,右,下
/*下面布局*/
             //新建组件和表单管理器
            QLineEdit *nameEdit=new QLineEdit();
            QComboBox *xingbie=new QComboBox();
            QFormLayout *layout2=new QFormLayout;
           layout2->addRow("姓名:",nameEdit);
           layout2->addRow("性别:",xingbie);
            //设置对齐
           layout2->setLabelAlignment(Qt::AlignRight);//标签右对齐
           layout2->setFormAlignment(Qt::AlignLeft);//窗口左

 /*总布局*/
         //新建垂直布局
            QVBoxLayout *layout=new QVBoxLayout;
//添加上下布局
           layout->addLayout(layout1);
           layout->addLayout(layout2);
  layout->setSpacing(50);
  setLayout(layout);

2.设置部件大小

讲解之前要先了解两个概念:大小提示(sizeHint)最小大小提示(minimumSize-Hint)

凡是继承自QWidget的类都有这两个属性,其中,sizeHint属性保存了部件的建议大小,对于不同的部件,默认拥有不同的sizeHint;

minimumSizeHint保存了一个建议的最小大小提示

需要说明的是,如果使用setMinimumSize()函数设置了部件的最小大小,那么最小大小提示将会被忽略。

这两个属性在使用布局时起到了很重要的作用。

下面再来看一下大小策略(sizePolicy)属性,它也是QWidget类的属性。
这个属性保存了部件的默认布局行为,在水平和垂直两个方向分别起作用,控制着部件在布局管理器的大小变化行为
sizePolicy属性的所有取值如图

可以看到,QSizePolicy与sizeHint()的值息息相关。

设置分隔符spacer,将其属性中的sizeHint的高度设置为100

可是它并没有改变达到100
它的sizeType设置为Expanding
把它改为Fixed,这样就行了,现在它的高宽才是实际的sizeHint的

下面再来了解一下伸缩因子(stretch factor)的概念。

前面讲垂直布局管理器时曾提到过它,其实它是用来设置部件间比例的。
界面上的字体选择框和一个按钮处于一个水平布局管理器中,现在想让它们的宽度比例为2:1,那么就可以单击对象栏中的horizontalLayout水平布局管理器对象,然后在它的属性栏中将layout Stretch属性设置为“2,1”,这样这个水平布局管理器中的两个部件的宽度就是2:1的比例了。

如果要在代码中进行设置,则可以在使用布局管理器的addWidget()函数添加部件的同时,在第二个参数中指定伸缩因子。

现在再来看一下窗体布局管理器的一些属性。
点击formLayout,其中属性栏中的几个属性的说明如图:

举个例子:把layoutFieldGrownPolicy属性,这里选择ExpandingFieldsGrow选项,这样性别和年龄二个输入框就没有那么宽了。

然后将界面中的"邮箱”标签改为“邮箱地址",在layoutLabelAlignment属性中选择AlignRight

下面来看一下QWidget类及其子类部件的设置大小的相关属性。
单击主界面,查看一下其属性栏,其最开始便是几个与大小有关的属性

这里的高度与宽度属性是现在界面的大小;
下面的sizePolicy属性可以设置大小策略以及伸缩因子;minimumSize属性用来设置最小值,这里改为200×150;maximumSize属性设置最大值,将其设置为500×350;sizeIncrement属性和baseSize属性是设置窗口改变大小的,一般不用设置,

如图所示。

最后看一下布局管理器的layoutSizeConstraint属性,它是用来约束窗口大小的,也就是说,这个只对顶级布局管理器有用,只对窗口有用,对其他子部件无用

然后运行程序,无法改变布局管理器窗口大小

3. 可扩展窗口

一个窗口可能有很多选项是扩充的,只有在必要的时候才显示出来,这时就可以使用一个按钮来隐藏或者显示多余的内容,就是所谓的可扩展窗口。

下面看一个具体的例子。
依然在前面的程序中进行更改。首先将界面上的pushButton显示文本更改为“显示可扩展窗口”,并在其属性栏选中checkable选项。然后转到它的toggled(bool)信号的槽,更改如下:

// 显隐窗口按钮
void MyWidget::on_pushButton_toggled(bool checked)
{
    ui->textEdit->setVisible(checked);  // 设置文本编辑器的显示和隐藏 此属性子部件是否可见
    if(checked) ui->pushButton->setText(tr("隐藏可扩展窗口"));
    else ui->pushButton->setText(tr("显示可扩展窗口"));
}

setvisible函数官网

这里使用按钮的按下与否来设置文本编辑器是否显示,并且改变按钮文本

为了显示效果,先让文本编辑器隐藏

ui->textEdit->hide();      // 让文本编辑器隐藏,也可以使用setVisible(false)函数

也可以

ui->setVisible(false)

效果:

按下后,checked成true,显示窗口,改变文本为隐藏窗口

4. 分裂器(QSplitter)

分裂器QSplitter类提供了一个分裂器部件。和QBoxLayout类似,可以完成布局管理器的功能,但是包含在它里面的部件,默认是可以随着分裂器的大小变化而变化的
比如一个按钮放在布局管理器中,它的垂直方向默认是不会被拉伸的,但是放到分裂器中就可以被拉伸。
还有一点不同就是,布局管理器继承自QObject类,而分裂器却是继承自QFrame类QFrame类又继承自QWidget类,也就是说,分裂器拥有QWidget类的特性,它是可见的,而且可以像QFrame一样设置边框

新建一个widget应用,项目名称为mysplitter,基类QWidget,类名为MyWidget。
打开ui
拖入四个按钮

使用分裂器水平布局

设置其frameShape为Box,frameShadow为Raised,lineWidth为5

设置伙伴

前面讲述窗体布局管理器时提到了设置一个标签和一个部件的伙伴关系。

其实伙伴(buddy)是在QLabel类中提出的一个概念。

因为一个标签经常用作一个交互式部件的说明,就像在讲窗体布局管理器时看到的那样,一个lineEdit部件前面有一个标签说明这个lineEdit的作用。

为了方便定位,QLabel提供了一个有用的机制,那就是提供了助记符来定位键盘焦点到对应的部件上,而这个部件就叫这个QLabel的伙伴。其中,助记符就是我们所说的加速键
使用英文标签时,在字符串的一个字母前面添加“&”符号,就可以指定这个标签的加速键是Alt加上这个字母
对于中文,需要在小括号中指定加速键字母,这个前面已经见过多次了。Qt设计器中也提供了伙伴设计模式,下面看一个例子。

新建项目mybuddy,基类选择QWidget,类名设为MyWidget
打开ui,大概这样键,

单击设计器上方的

进入伙伴设计模式

分别将各个标签跟它们后面的部件关联起来

按F3退出,可以看见所有的&符号不显示

按下alt+___ 那个字母==加速键符合哪个部件,光标到那个部件

如果要用函数设置伙伴关系,可以使用QLabel的setBuddy()函数就可以了

//设置伙伴关系
 ui->label->setBuddy(ui->pushButton);
 ui->label_2->setBuddy(ui->checkBox);
 ui->label_3->setBuddy(ui->lineEdit);
 ui->label_4->setBuddy(ui->spinBox);

可以通过帮助索引的Qt Designed‘s Buddy Editing Mode关键字查看或者F1

设置Tab键顺序

tab键–焦点转移下一个框架,从一个部件转移到另一个部件
在设计模式中,设计器提供了Tab键的设置功能。

显示出来顺序了,只要单击这些数字就可以更改顺序。
设置好以后,可以运行测试

按tab键会跳到下一个部件

代码实现:

//设置Tab键顺序
 setTabOrder(ui->lineEdit,ui->spinBox);//lineEdit在spinBox前面
 setTabOrder(ui->spinBox,ui->pushButton);//spinBox在pushButton前面
 setTabOrder(ui->pushButton,ui->checkBox);//pushbutton在checkBox前面

要传递关系 a,b; b,c ; c,d

定位器

位于主界面的下方,可以很方便地打开指定文件,定位到文档的指定行等

使用crtl+k过滤器
使用方法:“前缀符号+空格+要定位的内容“
下面举几个例子:
l 8---------------------跳转到第八行

再次按下crtl+k,输入“?qla”,

跳转到QLabel帮助界面

总结 一个良好的布局是必须的

相关文章