目录
[一. Tab Widget](#一. Tab Widget)
一. Tab Widget
你可以把 QTabWidget 想象成一个带标签的文件夹 或者浏览器窗口。
-
QTabWidget 本身 :它只是一个框架,包括顶部的标签栏 和中间的页面区域 。它本身不显示具体内容,它的工作是管理这些标签和页面。
-
每个标签页(QWidget):这才是真正存放用户界面内容的地方。每个标签页都是一个独立的、完整的 QWidget。你可以在里面放置按钮、文本框、表格、图片等任何其他控件,甚至可以再嵌套布局和其他容器。
这个是什么意思呢?
我们每次创建一个新项目,点进去一个新的.ui文件里面看看,我们发现默认就有下面这个控件,我们后续的控件都是放置在这上面的

我们在右侧可以看到

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


对吧!!
而我们的QTabWidget呢
我们可以往上面放一个看看


我们发现这个QTabWidget里面居然存的也是QWidget。!!!这就说明我们的QTabWidget里面的QWidget也能完成和最顶层的QWidget一样的功能!!!!!!
使⽤ QTabWidget 实现⼀个带有标签⻚的控件,可以往⾥⾯添加⼀些widget,进⼀步的就可以通过标 签⻚来切换.

1.1.核心属性
- tabPosition - 标签页所在的位置
这个属性决定了标签栏(显示标签标题的地方)在 QTabWidget
中的方位。它不是一个字符串,而是一个枚举值。
-
North(上方) :这是默认值。标签栏显示在控件的顶部,内容区域在下方。这是最常见和符合用户习惯的布局,类似于浏览器或属性设置窗口。
-
South(下方):标签栏显示在控件的底部,内容区域在上方。这种布局不太常见,但有时用于实现特殊的界面风格。
-
West(左侧):标签栏垂直显示在控件的左侧,内容区域在右侧。标签文本通常是垂直排列的。适用于高度大于宽度的窗口,或者当标签标题文字较长时。
-
East(右侧):标签栏垂直显示在控件的右侧,内容区域在左侧。与 West 类似,但更为少见。
简单来说:这个属性让你决定标签页的"选项卡"是放在窗口的哪一边。
- currentIndex - 当前选中标签页的索引
这个属性是一个整数,表示当前正在显示给用户的是第几个标签页。
-
从0开始计算:第一个标签页的索引是 0,第二个是 1,以此类推。
-
用途 :通过读取这个属性,你可以知道用户当前正在查看哪个标签页。通过设置这个属性(例如
setCurrentIndex(2)
),你可以用代码控制切换到第三个标签页。 -
如果没有选中任何标签页(理论上很少见),其值为 -1。
- currentTabText - 当前选中标签页的文本
这个属性是当前被选中的标签页在标签栏上显示的标题文字。
- 用途:你可以获取这个值来知道当前标签页叫什么名字。同样,你也可以通过设置这个属性来动态改变当前标签页的标题。
- currentTabName - 当前选中标签页的名字
注意 :在标准的 Qt QTabWidget
中,并没有一个直接叫做 currentTabName
的属性。这很可能指的是与 currentTabText
相同的概念,或者是每个标签页背后对应的 QWidget
的 objectName
属性。
- 如果指代的是
objectName
:这是在代码中用于标识对象的内部名称,通常不直接显示给用户,而是在编程时用于查找和区分不同的控件。
- currentTabIcon - 当前选中标签页的图标
这个属性是当前被选中的标签页在标签栏上显示的图标。
- 用途 :它可以是一个小图片(如
.png
文件),与文本一起或替代文本来更直观地表示标签页的功能。例如,一个"设置"标签页可能使用齿轮图标。
- currentTabToolTip - 当前选中标签页的提示信息
这个属性是当用户将鼠标指针悬停在当前标签页的标签上时,弹出的一个简短提示信息。
- 用途:用于提供额外的说明。当标签标题因为空间不足而无法完整显示,或者你想提供比标题更详细的解释时,这个功能非常有用。
- tabsCloseable - 标签页是否可以关闭
这是一个布尔值属性(True/False)。
-
当设置为 True :每个标签页的标签上都会显示一个关闭按钮(通常是一个"×")。用户点击这个按钮可以关闭该标签页。
-
默认值为 False:标签页没有关闭按钮,无法通过界面直接关闭。
-
重要提示 :仅仅设置这个属性为 True 并不会自动移除标签页背后的 Widget。你需要连接
tabCloseRequested(int index)
信号到一个自定义的槽函数,在该函数中处理关闭和清理工作。
- movable - 标签页是否可以移动
这是一个布尔值属性(True/False)。
-
当设置为 True :用户可以通过鼠标拖动 来改变标签页的顺序。例如,你可以把第二个标签页拖到第一个位置。
-
默认值为 False:标签页的顺序是固定的,用户无法通过拖动来改变。
1.2.核心信号
- currentChanged(int index)
核心含义: 当前活动的、显示给用户的标签页发生了改变。
详细解读:
-
触发时机 :这是最重要的信号,它标志着用户视野的切换。无论通过何种方式,只要最终导致显示给用户的标签页发生了变化,这个信号就会被触发。
-
参数 :
index
是新被激活(成为当前页)的标签页的编号。编号通常从 0 开始。 -
触发场景(非常广泛):
-
鼠标点击:用户用鼠标点击了一个非当前活动的标签页标题条。这是最常见的方式。
-
键盘快捷键 :例如,按
Ctrl+Tab
循环切换标签页。 -
代码控制 :在程序内部通过代码(例如
setCurrentIndex(2)
)主动切换当前标签页。 -
关闭其他标签页:当用户关闭了当前正在看的标签页时,系统会自动切换到另一个标签页,此时也会触发此信号,参数是那个"另一个标签页"的编号。
-
可以类比为: 你面前有一个放着多份文件的文件夹,你从正在阅读的A文件切换到了 B文件。这个"切换到"的动作,就是 currentChanged
。
典型用途:
-
懒加载/延迟加载:当切换到一个标签页时,才去加载该页内需要大量计算或网络请求的内容,以提高程序启动速度。
-
保存状态:在离开一个标签页(即该页不再是当前页)时,自动保存用户在该页面的操作(如未提交的表单、滚动条位置等)。
-
更新界面:根据当前激活的标签页,更新菜单栏、工具栏或状态栏的内容。例如,在"编辑"标签页下显示格式工具栏,在"视图"标签页下隐藏它。
- tabBarClicked(int index)
核心含义: 用户用鼠标点击了标签条上的某个标签,无论它是否已经是当前页。
详细解读:
-
触发时机 :仅由鼠标点击在标签条上触发。它关注的是"点击"这个物理动作本身。
-
参数 :
index
是被点击的那个标签页的编号。 -
关键区别:
-
它与
currentChanged
有重叠,但范围更窄。 -
如果你点击的已经是当前活动的标签页 ,
currentChanged
不会触发 (因为当前页没变),但tabBarClicked
会触发。 -
它不关心点击后视图是否改变,只关心"点没点"。
-
可以类比为: 你用手指去指文件夹上的某个标签,无论这个标签对应的文件是不是你正在看的那一页,只要你"指"了这个动作发生了,就算。
典型用途:
-
刷新操作 :实现"点击当前活动标签页标题刷新本页内容"的功能。因为点击当前页不会触发
currentChanged
,但会触发tabBarClicked
。 -
自定义菜单:在标签条上点击右键弹出上下文菜单。
-
统计与分析:记录用户点击各个标签的频次,而不关心是否真的发生了切换。
- tabBarDoubleClicked(int index)
核心含义: 用户用鼠标双击了标签条上的某个标签。
详细解读:
-
触发时机 :仅由鼠标双击 在标签条上触发。它是
tabBarClicked
的更特定版本。 -
参数 :
index
是被双击的那个标签页的编号。 -
行为逻辑 :一次双击操作通常会先触发一次
tabBarClicked
(对应第一次点击),然后再触发tabBarDoubleClicked
。你需要小心处理,避免一个操作被执行两次。 -
与页面状态无关 :和
tabBarClicked
一样,无论被双击的标签页是不是当前页,都会触发。
典型用途:
-
重命名标签页:这是一个非常经典和通用的交互设计。双击标签标题,让其进入可编辑状态,允许用户自定义标签页的名称。
-
在新窗口中打开:双击某个标签,将其分离到一个独立的窗口中。
-
关闭标签页:有些设计也用双击来关闭标签页(虽然更常见的是中键点击或点击关闭按钮)。
- 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中,控件(也称为部件)的父子关系是管理内存和布局的关键。
- 当一个控件被创建时,如果指定了父控件,那么它就会成为父控件的子控件,并且显示在父控件的区域内。
- 此外,当父控件被销毁时,它会自动销毁其所有子控件,从而避免内存泄漏。
就拿下面两个例子来说:
-
QLabel* label = new QLabel(ui->tab);
-
QLabel* label = new QLabel(this);
这里,ui->tab
和 this
分别是两个不同的父控件。
下面详细解释:
第一个例子: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的某个标签页)上,实际上就是设置了该控件以这个标签页为父控件。
总结:父控件决定了子控件的显示区域和生命周期。子控件会显示在父控件的内部,并且当父控件被销毁时,子控件也会被自动销毁。
接着给我们的两个按钮配置一下槽函数

我们运行一下


我们点击




很完美了。