【Qt】容器类控件——QTabWidget

目录

[一. Tab Widget](#一. Tab Widget)

1.1.核心属性

1.2.核心信号

1.3.示例------使用标签页管理多组控件


一. Tab Widget

你可以把 QTabWidget 想象成一个带标签的文件夹 或者浏览器窗口

  • QTabWidget 本身 :它只是一个框架,包括顶部的标签栏 和中间的页面区域 。它本身不显示具体内容,它的工作是管理这些标签和页面。

  • 每个标签页(QWidget):这才是真正存放用户界面内容的地方。每个标签页都是一个独立的、完整的 QWidget。你可以在里面放置按钮、文本框、表格、图片等任何其他控件,甚至可以再嵌套布局和其他容器。

这个是什么意思呢?

我们每次创建一个新项目,点进去一个新的.ui文件里面看看,我们发现默认就有下面这个控件,我们后续的控件都是放置在这上面的

我们在右侧可以看到

发现这个控件就是QWidget。

我们往这个QWidget控件上面放置的控件,都成为了这个QWidget的子类。

对吧!!

而我们的QTabWidget呢

我们可以往上面放一个看看

我们发现这个QTabWidget里面居然存的也是QWidget。!!!这就说明我们的QTabWidget里面的QWidget也能完成和最顶层的QWidget一样的功能!!!!!!


使⽤ QTabWidget 实现⼀个带有标签⻚的控件,可以往⾥⾯添加⼀些widget,进⼀步的就可以通过标 签⻚来切换.

1.1.核心属性

  1. tabPosition - 标签页所在的位置

这个属性决定了标签栏(显示标签标题的地方)在 QTabWidget 中的方位。它不是一个字符串,而是一个枚举值。

  • North(上方) :这是默认值。标签栏显示在控件的顶部,内容区域在下方。这是最常见和符合用户习惯的布局,类似于浏览器或属性设置窗口。

  • South(下方):标签栏显示在控件的底部,内容区域在上方。这种布局不太常见,但有时用于实现特殊的界面风格。

  • West(左侧):标签栏垂直显示在控件的左侧,内容区域在右侧。标签文本通常是垂直排列的。适用于高度大于宽度的窗口,或者当标签标题文字较长时。

  • East(右侧):标签栏垂直显示在控件的右侧,内容区域在左侧。与 West 类似,但更为少见。

简单来说:这个属性让你决定标签页的"选项卡"是放在窗口的哪一边。

  1. currentIndex - 当前选中标签页的索引

这个属性是一个整数,表示当前正在显示给用户的是第几个标签页。

  • 从0开始计算:第一个标签页的索引是 0,第二个是 1,以此类推。

  • 用途 :通过读取这个属性,你可以知道用户当前正在查看哪个标签页。通过设置这个属性(例如 setCurrentIndex(2)),你可以用代码控制切换到第三个标签页。

  • 如果没有选中任何标签页(理论上很少见),其值为 -1。

  1. currentTabText - 当前选中标签页的文本

这个属性是当前被选中的标签页在标签栏上显示的标题文字

  • 用途:你可以获取这个值来知道当前标签页叫什么名字。同样,你也可以通过设置这个属性来动态改变当前标签页的标题。
  1. currentTabName - 当前选中标签页的名字

注意 :在标准的 Qt QTabWidget 中,并没有一个直接叫做 currentTabName 的属性。这很可能指的是与 currentTabText 相同的概念,或者是每个标签页背后对应的 QWidgetobjectName 属性。

  • 如果指代的是 objectName:这是在代码中用于标识对象的内部名称,通常不直接显示给用户,而是在编程时用于查找和区分不同的控件。
  1. currentTabIcon - 当前选中标签页的图标

这个属性是当前被选中的标签页在标签栏上显示的图标

  • 用途 :它可以是一个小图片(如 .png 文件),与文本一起或替代文本来更直观地表示标签页的功能。例如,一个"设置"标签页可能使用齿轮图标。
  1. currentTabToolTip - 当前选中标签页的提示信息

这个属性是当用户将鼠标指针悬停在当前标签页的标签上时,弹出的一个简短提示信息。

  • 用途:用于提供额外的说明。当标签标题因为空间不足而无法完整显示,或者你想提供比标题更详细的解释时,这个功能非常有用。
  1. tabsCloseable - 标签页是否可以关闭

这是一个布尔值属性(True/False)。

  • 当设置为 True :每个标签页的标签上都会显示一个关闭按钮(通常是一个"×")。用户点击这个按钮可以关闭该标签页。

  • 默认值为 False:标签页没有关闭按钮,无法通过界面直接关闭。

  • 重要提示 :仅仅设置这个属性为 True 并不会自动移除标签页背后的 Widget。你需要连接 tabCloseRequested(int index) 信号到一个自定义的槽函数,在该函数中处理关闭和清理工作。

  1. movable - 标签页是否可以移动

这是一个布尔值属性(True/False)。

  • 当设置为 True :用户可以通过鼠标拖动 来改变标签页的顺序。例如,你可以把第二个标签页拖到第一个位置。

  • 默认值为 False:标签页的顺序是固定的,用户无法通过拖动来改变。

1.2.核心信号

  1. currentChanged(int index)

核心含义: 当前活动的、显示给用户的标签页发生了改变。

详细解读:

  • 触发时机 :这是最重要的信号,它标志着用户视野的切换。无论通过何种方式,只要最终导致显示给用户的标签页发生了变化,这个信号就会被触发。

  • 参数index 是新被激活(成为当前页)的标签页的编号。编号通常从 0 开始。

  • 触发场景(非常广泛)

    1. 鼠标点击:用户用鼠标点击了一个非当前活动的标签页标题条。这是最常见的方式。

    2. 键盘快捷键 :例如,按 Ctrl+Tab 循环切换标签页。

    3. 代码控制 :在程序内部通过代码(例如 setCurrentIndex(2))主动切换当前标签页。

    4. 关闭其他标签页:当用户关闭了当前正在看的标签页时,系统会自动切换到另一个标签页,此时也会触发此信号,参数是那个"另一个标签页"的编号。

可以类比为: 你面前有一个放着多份文件的文件夹,你从正在阅读的A文件切换到了 B文件。这个"切换到"的动作,就是 currentChanged

典型用途:

  • 懒加载/延迟加载:当切换到一个标签页时,才去加载该页内需要大量计算或网络请求的内容,以提高程序启动速度。

  • 保存状态:在离开一个标签页(即该页不再是当前页)时,自动保存用户在该页面的操作(如未提交的表单、滚动条位置等)。

  • 更新界面:根据当前激活的标签页,更新菜单栏、工具栏或状态栏的内容。例如,在"编辑"标签页下显示格式工具栏,在"视图"标签页下隐藏它。


  1. tabBarClicked(int index)

核心含义: 用户用鼠标点击了标签条上的某个标签,无论它是否已经是当前页。

详细解读:

  • 触发时机仅由鼠标点击在标签条上触发。它关注的是"点击"这个物理动作本身。

  • 参数index 是被点击的那个标签页的编号。

  • 关键区别

    • 它与 currentChanged 有重叠,但范围更窄。

    • 如果你点击的已经是当前活动的标签页currentChanged 不会触发 (因为当前页没变),但 tabBarClicked 会触发

    • 它不关心点击后视图是否改变,只关心"点没点"。

可以类比为: 你用手指去指文件夹上的某个标签,无论这个标签对应的文件是不是你正在看的那一页,只要你"指"了这个动作发生了,就算。

典型用途:

  • 刷新操作 :实现"点击当前活动标签页标题刷新本页内容"的功能。因为点击当前页不会触发 currentChanged,但会触发 tabBarClicked

  • 自定义菜单:在标签条上点击右键弹出上下文菜单。

  • 统计与分析:记录用户点击各个标签的频次,而不关心是否真的发生了切换。


  1. tabBarDoubleClicked(int index)

核心含义: 用户用鼠标双击了标签条上的某个标签。

详细解读:

  • 触发时机仅由鼠标双击 在标签条上触发。它是 tabBarClicked 的更特定版本。

  • 参数index 是被双击的那个标签页的编号。

  • 行为逻辑 :一次双击操作通常会先触发一次 tabBarClicked(对应第一次点击),然后再触发 tabBarDoubleClicked。你需要小心处理,避免一个操作被执行两次。

  • 与页面状态无关 :和 tabBarClicked 一样,无论被双击的标签页是不是当前页,都会触发。

典型用途:

  • 重命名标签页:这是一个非常经典和通用的交互设计。双击标签标题,让其进入可编辑状态,允许用户自定义标签页的名称。

  • 在新窗口中打开:双击某个标签,将其分离到一个独立的窗口中。

  • 关闭标签页:有些设计也用双击来关闭标签页(虽然更常见的是中键点击或点击关闭按钮)。


  1. tabCloseRequested(int index)

核心含义: 用户发出了一个"请求"要关闭某个标签页。

详细解读:

  • 触发时机 :当用户尝试关闭一个标签页时触发。注意,它只是一个"请求",并不代表标签页已经被关闭了。

  • 参数index 是用户请求关闭的那个标签页的编号。

  • 关键区别 :这个信号是"请求式"的,而 currentChanged 在关闭时是"结果式"的。

  • 触发方式

    • 点击标签页上的"X"关闭按钮(最常见)。

    • 通过鼠标中键点击标签(常见于浏览器)。

    • 通过快捷键(如 Ctrl+W)。

    • 通过右键菜单的"关闭"选项。

典型用途:

  • 关闭前确认 :这是最重要的用途。在槽函数中,你可以检查该标签页内的内容是否已经保存。如果用户有未保存的修改,可以弹出一个对话框询问"是否保存更改?",并根据用户选择决定是执行关闭 还是取消关闭

  • 执行关闭逻辑 :在这个信号的槽函数里,你才真正地去销毁该标签页内的组件、释放资源,并从 QTabWidget 中移除该标签页。

  • 数据保存:在真正关闭前,自动保存数据。

1.3.示例------使用标签页管理多组控件

我们创建一个新的项目

我们这个时候直接运行一下程序

事实上呢

  • QTabWidget 中的每个标签⻚都是⼀个QWidget
  • 点击标签⻚,就可以直接切换.
  • 右键 QTabWidget ,可以添加标签⻚或者删除标签⻚.

比如说,我们在第一个标签页里面放一个Label

这个时候我们点击Tab2

我们发现刚刚那个Label没有了。

这个时候我们在Tab2里面也添加一个Label

这个时候我们看看右边的状态栏

我们运行一下

我们点击Tab 2看看

怎么样?两个Label就隔离开来了。

我们现在是不是就更好的理解------QTabWidget 中的每个标签⻚都是⼀个QWidget 这一句话了

当然了,我们的QTabWidget默认就是2个标签页,在.ui文件里面我们添加标签页可以像下面这样子

好了上面只是一个小插曲,我们回到我们的项目。

先删除掉我们在上面添加的Label

现在我们就来编写我们的代码

这里涉及一个新的知识点

在Qt中,控件(也称为部件)的父子关系是管理内存和布局的关键。

  • 当一个控件被创建时,如果指定了父控件,那么它就会成为父控件的子控件,并且显示在父控件的区域内。
  • 此外,当父控件被销毁时,它会自动销毁其所有子控件,从而避免内存泄漏。

就拿下面两个例子来说:

  1. QLabel* label = new QLabel(ui->tab);

  2. QLabel* label = new QLabel(this);

这里,ui->tabthis 分别是两个不同的父控件。

下面详细解释:

第一个例子:QLabel* label = new QLabel(ui->tab);

ui->tab是一个已经存在的标签页(QTabWidget中的某个标签页),那么这个QLabel将成为这个标签页的子控件。因此,它会显示在这个标签页的内部,并且其位置相对于这个标签页的左上角(除非使用布局管理器或者手动移动)。

第二个例子:QLabel* label = new QLabel(this);

这里的this通常指的是当前类的实例,如果当前类是一个窗口(比如QWidget),那么这个QLabel将成为窗口的子控件。因此,它会显示在窗口的客户区(即窗口内部,不包括标题栏和边框)内,位置相对于窗口的左上角。

具体显示在哪个位置,还取决于是否使用了布局管理器(layout manager)。如果没有使用布局,那么需要手动设置子控件的位置和大小;如果使用了布局,那么布局会自动安排子控件的位置和大小。

举个例子:

假设我们有一个QMainWindow,它有一个中央部件(central widget),而中央部件是一个QTabWidget,其中有一个标签页叫"tab1"。

那么:

  • 如果你在QMainWindow的构造函数中这样做:

    QLabel *label1 = new QLabel(this);

    那么label1将直接成为QMainWindow的子控件,它可能会被中央部件覆盖(因为中央部件通常占据了整个客户区),所以你可能看不到它,或者需要设置位置。

  • 如果你这样做:

    QLabel *label2 = new QLabel(ui->tab1);

    那么label2将成为标签页"tab1"的子控件,因此它只会出现在"tab1"标签页中。

另外,注意:在Qt Designer中,你拖放一个控件到某个容器(比如QTabWidget的某个标签页)上,实际上就是设置了该控件以这个标签页为父控件。

总结:父控件决定了子控件的显示区域和生命周期。子控件会显示在父控件的内部,并且当父控件被销毁时,子控件也会被自动销毁。


接着给我们的两个按钮配置一下槽函数

我们运行一下

我们点击

很完美了。

相关推荐
hqwest3 小时前
QT肝8天07--连接数据库
开发语言·数据库·c++·qt·sqlite·上位机·qt开发
ManThink Technology3 小时前
实用的LoRaWAN 应用层协议规范
开发语言·php
敲代码的嘎仔3 小时前
牛客算法基础noob59 简写单词
java·开发语言·数据结构·程序人生·算法·leetcode·学习方法
catchadmin3 小时前
如何在 PHP 升级不踩坑?学会通过阅读 RFC 提前预知版本变化
开发语言·后端·php
tpoog4 小时前
[C++项目组件]Elasticsearch简单介绍
开发语言·c++·elasticsearch
特立独行的猫a5 小时前
C 语言各种指针详解
java·c语言·开发语言
彭于晏Yan7 小时前
MyBatis-Plus使用动态表名分表查询
java·开发语言·mybatis
MediaTea11 小时前
Python IDE:Spyder
开发语言·ide·python
不枯石12 小时前
Matlab通过GUI实现点云的均值滤波(附最简版)
开发语言·图像处理·算法·计算机视觉·matlab·均值算法