【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的某个标签页)上,实际上就是设置了该控件以这个标签页为父控件。

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


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

我们运行一下

我们点击

很完美了。

相关推荐
用户805533698035 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
xcyxiner5 天前
DicomViewer (vcpkg Windows和ubuntu编译)7
qt
Quz10 天前
QML Hello World 入门示例
qt
xcyxiner13 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner14 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner14 天前
DicomViewer (添加模型类)3
qt
xcyxiner15 天前
DicomViewer (目录调整) 2
qt
xcyxiner15 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
LDR00617 天前
Type-C 快充全面升级!LDR6601 赋能个人护理便携电机,重塑剃须刀 / 理发器新体验
c语言·开发语言
雪碧聊技术17 天前
Tree.js是什么?一文讲透
开发语言·javascript·ecmascript