QT跨平台应用程序开发框架(9)—— 容器类控件

目录

一,关于容器类控件

[二,Group Box](#二,Group Box)

[2.1 主要属性](#2.1 主要属性)

[2.2 点餐系统再升级](#2.2 点餐系统再升级)

[三,Tab Widget](#三,Tab Widget)

[3.1 主要属性](#3.1 主要属性)

[3.2 代码示例](#3.2 代码示例)

四,布局管理器

[4.1 垂直布局](#4.1 垂直布局)

[4.2 水平布局](#4.2 水平布局)

[4.3 网格布局](#4.3 网格布局)

[4.4 拉伸系数](#4.4 拉伸系数)

[4.5 表单布局](#4.5 表单布局)

五,Spacer

一,关于容器类控件

容器类控件指的就是这个容器内可以容纳一些其它的控件

不同于多元素控件,多元素控件包含的是一个一个自定义好的 "item" 对象;而容器内控件包含的直接就是我们前面介绍的一堆的控件

二,Group Box

2.1 主要属性

QGroupBox 实现一个带有标题的分组框,可以把其他的控件放到里面称为一组,这个分组框也没有什么强大的功能,只是让界面看起来好看一些,主要属性如下:

属性 说明
title 分组框的标题
alignment 分组框内部内容的对齐方式
flat 是否是"扁平"模式
checkable 是否可选择 设为 true 则在title前方会多出一个可勾选的部分
checked 描述分组框的选择状态(前提是checkable为true)

2.2 点餐系统再升级

然后内部的逻辑我们就不实现了,因为和前面的是一样的:QT跨平台应用程序开发框架(7)------ 常用输入类控件-CSDN博客

三,Tab Widget

3.1 主要属性

QTabWidget 表示一个带有标签页的控件,可以在里面添加一些 widget,可以通过标签页来切换,可以类比下浏览器上方的标签页,主要属性如下:

属性 说明
tabPosition 标签⻚所在的位置 * North:上方 * South:下方 * West:左侧 * East:右侧
currentIndex 当前选中了第几个标签页(从0开始计算)
currentTabText 当前选中的标签页的文本
currentTabName 当前选中的标签页的名字
currentTabIcon 当前选中的标签页的图标
currentTabToolTip 当前选中的标签页的提示信息
tabsCloseable 标签页是否可以关闭
movable 标签页是否可以移动

主要信号如下:

信号 说明
currentChanged(int) 在标签页发生切换时触发,参数为被点击的选项卡编号
tabBarClicked(int) 在点击选项卡的标签条的时候触发,参数为被点击的选项卡编号
tabBarDoubleClicked(int) 在双击选项卡的标签条的时候触发,参数为被点击的选项卡编号
tabCloseRequest(int) 在标签页关闭时触发,参数为被关闭的选项卡编号

3.2 代码示例

我们下面实现的程序期望是:

  • 创建一个程序,带有一个 TableWidget 作为标签页
  • 提供两个按钮,分别创建新的标签页,关闭当前选中的标签页
  • 当切换标签页时,也能感知到变化

先创建下列控件:

代码如下:

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include<QLabel>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //先在每个标签页添加一个 label
    QLabel* l1 = new QLabel(ui->tab);
    l1->setText("标签页1");
    l1->resize(100, 50);

    QLabel* l2 = new QLabel(ui->tab_2);
    l2->setText("标签页2");
    l2->resize(100, 50);
}

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


void Widget::on_pushButton_clicked()
{
    QWidget* w = new QWidget();
    int count = ui->tabWidget->count(); //获取当前标签页数量,新增时 + 1
    ui->tabWidget->addTab(w, QString("Tab ") + QString::number(count + 1));
    //addTab表示创建新的标签页,第一个参数表示要添加的控件,第二个参数表示新增标签页的标题
    //也可以添加一个输入框,让用户输入标签页标题

    QLabel* label = new QLabel(w);
    label->setText(QString("标签页 ") + QString::number(count + 1));
    label->resize(100, 50);
    
    ui->tabWidget->setCurrentIndex(count + 1); //设置选中新标签页
}

void Widget::on_pushButton_2_clicked()
{
    int index = ui->tabWidget->currentIndex(); //获取当前选中标签页的下标
    ui->tabWidget->removeTab(index); //删除标签页
}

void Widget::on_tabWidget_currentChanged(int index)
{
    //当标签页切换时,触发此信号
}

效果如下:

四,布局管理器

4.1 垂直布局

问题:为什么要有布局管理器?

解答:我们前面使用ui创建界面时,都是手动拖拽方式来布局的,其实这种方式不科学

  • 手动布局方式很复杂,而且不精确
  • 无法对窗口大小进行自适应

所以需要布局管理器使控件的布局更加灵活,有四种

QVBoxLayout 表示垂直布局管理器,V 是 vertical 的缩写,主要属性如下:

属性 说明
layoutLeftMargin 左侧边距
layoutRightMargin 右侧边距
layoutTopMargin 上方边距
layoutBottomMargin 下方边距
layoutSpacing 相邻元素之间的间距

下面是布局管理器的基本用法:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    
    //先创建三个按钮,然后使用布局管理器管理起来
    QPushButton* b1 = new QPushButton("按钮1");
    QPushButton* b2 = new QPushButton("按钮2");
    QPushButton* b3 = new QPushButton("按钮3");
    
    //创建布局管理器对象
    QVBoxLayout* layout = new QVBoxLayout();
    layout->addWidget(b1);
    layout->addWidget(b2);
    layout->addWidget(b3);
    
    //把布局管理器添加到窗口中
    this->setLayout(layout); //
}

效果如下:

每个 Widget 只能设置一个布局管理器, 但是可以通过拖拽方式创建两个布局遍历器,但是这样创建的布局管理器仅仅只会将内部控件重新组合位置,并不会像上面一样随着窗口大小改变

因为在 Qt Designer 中创建的 layout,是先创建了一个 Widget,然后再在这个新的 Widget 中添加了一个 layout

4.2 水平布局

QHBoxLayout 表示水平的布局管理器,H 是 horizontal 的缩写,核心属性和垂直布局管理器一致:

属性 说明
layoutLeftMargin 左侧边距
layoutRightMargin 右侧边距
layoutTopMargin 上方边距
layoutBottomMargin 下方边距
layoutSpacing 相邻元素之间的间距

而且在使用上也和垂直布局管理器一样的,下面简单演示一下:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //先创建三个按钮,然后使用布局管理器管理起来
    QPushButton* b1 = new QPushButton("按钮1");
    QPushButton* b2 = new QPushButton("按钮2");
    QPushButton* b3 = new QPushButton("按钮3");

    //创建水平布局管理器对象
    QHBoxLayout* layout = new QHBoxLayout();
    layout->addWidget(b1);
    layout->addWidget(b2);
    layout->addWidget(b3);

    //把布局管理器添加到窗口中
    this->setLayout(layout); //
}

布局管理器之间也能进行嵌套,如下代码:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QVBoxLayout* vlayout = new QVBoxLayout(); //垂直布局管理器
    this->setLayout(vlayout);

    QPushButton* b1 = new QPushButton("按钮1");
    QPushButton* b2 = new QPushButton("按钮2");
    vlayout->addWidget(b1);
    vlayout->addWidget(b2);

    QHBoxLayout* hlayout = new QHBoxLayout(); //水平布局管理器
    QPushButton* b3 = new QPushButton("按钮3");
    QPushButton* b4 = new QPushButton("按钮4");
    hlayout->addWidget(b3);
    hlayout->addWidget(b4);

    vlayout->addLayout(hlayout);
}

效果如下:

4.3 网格布局

QGridLayout 用来实现网格布局的效果,可以达到 M * N 的这种网格效果,主要属性和 QHBoxLayout 类似,但是设置 spacing 的时候是按照垂直水平两个方向来设置的

属性 说明
layoutLeftMargin 左侧边距
layoutRightMargin 右侧边距
layoutTopMargin 上方边距
layoutBottomMargin 下方边距
layoutHorizontalSpacing 相邻元素之间水平方向的间距
layoutVerticalSpacing 相邻元素之间垂直方向的间距
layoutRowStretch 行方向的拉伸系数
layoutColumnStretch 列方向的拉伸系数

如下代码:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QPushButton* b1 = new QPushButton("按钮1");
    QPushButton* b2 = new QPushButton("按钮2");
    QPushButton* b3 = new QPushButton("按钮3");
    QPushButton* b4 = new QPushButton("按钮4");


    QGridLayout* layout = new QGridLayout();
//    layout->addWidget(b1, 0, 0); //需要指定行和列
//    layout->addWidget(b2, 0, 1); //第 0 行,第 1 列
//    layout->addWidget(b3, 1, 0);
//    layout->addWidget(b4, 1, 1);

    //我们还可以更灵活的指定按钮的位置,如下:
    layout->addWidget(b1, 0, 0); //需要指定行和列
    layout->addWidget(b2, 1, 1); //第 0 行,第 1 列
    layout->addWidget(b3, 2, 2);
    layout->addWidget(b4, 3, 3);
    this->setLayout(layout);
}

当列号相同时,效果相当于水平布局;当行号相同时,相当于垂直布局了

4.4 拉伸系数

  • 我们上面创建的布局管理器中的控件的各种属性,比如宽度高度等间距等都是一样的
  • 此时当我们需要创建出不同尺寸的控件时,可以通过拉伸系数来设置
  • 拉伸系数相当于控件之前尺寸的比例

下面是演示拉伸系数代码演示:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //创建 9 个按钮,使用网格布局按照3 * 3 的方式排列
    QPushButton* b1 = new QPushButton("按钮1");
    QPushButton* b2 = new QPushButton("按钮2");
    QPushButton* b3 = new QPushButton("按钮3");
    QPushButton* b4 = new QPushButton("按钮4");
    QPushButton* b5 = new QPushButton("按钮5");
    QPushButton* b6 = new QPushButton("按钮6");
    QPushButton* b7 = new QPushButton("按钮7");
    QPushButton* b8 = new QPushButton("按钮8");
    QPushButton* b9 = new QPushButton("按钮9");

    QGridLayout* layout = new QGridLayout();
    layout->addWidget(b1, 0, 0);
    layout->addWidget(b2, 0, 1);
    layout->addWidget(b3, 0, 2);
    layout->addWidget(b4, 1, 0);
    layout->addWidget(b5, 1, 1);
    layout->addWidget(b6, 1, 2);
    layout->addWidget(b7, 2, 0);
    layout->addWidget(b8, 2, 1);
    layout->addWidget(b9, 2, 2);

    this->setLayout(layout);

    //设置水平拉伸系数,期望是让每一列的尺寸都不一样
    //设置列方向拉伸系数,第一个参数是列数,第二个是拉伸的系数
    layout->setColumnStretch(0, 0); //如果拉伸系数设为0,则表示不参与拉伸,此时按钮宽度是固定值
    layout->setColumnStretch(1, 1);
    layout->setColumnStretch(2, 2);

    //设置垂直拉伸系数,QGridLayout 也提供了 setRowStretch 设置行之间的拉伸系数
    //但是直接设置没有效果,是因为 SizePolicy 的影响
    //由于按钮的垂直方向默认没有拉伸开,而水平方向默认是拉伸开的
    //所以需要把按钮的 sizePolicy 属性设置为 QSizePolicy::Expanding 才行
    b1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); //表示让按钮的垂直和水平都拉伸开
    b2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    b3->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    b4->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    b5->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    b6->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    b7->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    b8->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
    b9->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);

    //正式设置拉伸系数
    layout->setRowStretch(0, 0);
    layout->setRowStretch(1, 1);
    layout->setRowStretch(2, 2);

}

效果如下:

4.5 表单布局

QFormLayout 是 QGridLayout 的特殊情况,专门用于实现两列表单的布局,比如让用户填写信息的常见,左侧为文字提示,右侧为输入框,如下代码:

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 创建 layout
    QFormLayout* layout = new QFormLayout();
    this->setLayout(layout);
    // 创建三个 layout
    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);

}

五,Spacer

使用布局管理器时,可能需要在控件之间添加一段空白,就可以使用 QSpacerItem 来表示

主要属性:

属性 说明
width 宽度
height 高度
dData 水平方向的sizePolicy * QSizePolicy::Ignored:忽略控件的尺寸,不对布局产生影响 * QSizePolicy::Minimum :控件的最小尺寸为固定值,布局时不会超过该值 * QSizePolicy::Maximum:控件的最大尺存为固定值,布局时不会小于该值。 * QSizePolicy::Preferred:控件的理想尺寸为固定值,布局时会尽量接近该值 * QSizePolicy::Expanding:控件的尺寸可以根据空间调整,尽可能占据更多空间 * QSizePolicy::Shrinking:控件的尺寸可以根据空间调整,尽可能缩小以适应空间
vData 垂直防线的 sizePolicy,选项同上

假设我们使用垂直布局创建两个按钮,但是直接创建的话两个按钮是挨在一起的,我们想让两个按钮中间隔开些距离,代码如下:

cpp 复制代码
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);
    //在两个按钮中间添加空⽩
    layout->addSpacerItem(spacer); //放在哪里就在哪里添加空白,比如放到上面按钮前面,就是在前面添加空白
    layout->addWidget(btn2);
}
相关推荐
赵英英俊2 小时前
Python day15
开发语言·python
zxsd_xyz3 小时前
基于LabVIEW与Python混合编程的变声器设计与实现
开发语言·python·labview
遇见尚硅谷3 小时前
C语言:20250712笔记
c语言·开发语言·数据结构
☞下凡☜3 小时前
C语言(20250711)
linux·c语言·开发语言
二进制person3 小时前
数据结构--准备知识
java·开发语言·数据结构
半梦半醒*3 小时前
H3CNE综合实验之机器人
java·开发语言·网络
laoliu19965 小时前
GGE Lua 详细教程
开发语言·junit·lua
勇闯逆流河5 小时前
【C++】list及其模拟实现
开发语言·c++
liulilittle6 小时前
游戏加速器核心技术:动态超发
开发语言·网络·c++·网络协议·游戏·加速器·游戏加速
Humbunklung6 小时前
Rust 模块系统:控制作用域与私有性
开发语言·后端·rust