C++ Qt开发:TabWidget实现多窗体功能
Qt 是一个跨平台C++图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍TabWidget标签组件的常用方法及灵活运用。
QTabWidget 是Qt中用于实现标签页(tabbed interface)的控件,可以在一个窗口内切换不同的页面。在开发窗体应用时通常会伴随功能的分页,使用TabWidget并配合自定义Dialog组件,即可实现一个复杂的多窗体分页结构,此类布局方式也是多数软件通用的方案。
以下是 QTabWidget 的一些常用方法,以表格形式概述:
| 方法签名 | 描述 |
|---|---|
QTabWidget(QWidget *parent = nullptr) | 构造函数,创建一个 QTabWidget 对象。 |
int addTab(QWidget *page, const QString &label) | 添加一个标签页,参数 page 为标签页的内容,label 为标签页的标签文本。返回新添加标签页的索引。 |
void insertTab(int index, QWidget *page, const QString &label) | 在指定索引位置插入一个标签页。 |
void removeTab(int index) | 移除指定索引位置的标签页。 |
int currentIndex() const | 返回当前活动标签页的索引。 |
void setCurrentIndex(int index) | 设置当前活动标签页的索引。 |
QWidget *currentWidget() const | 返回当前活动标签页的内容窗口。 |
int count() const | 返回标签页的总数。 |
QWidget *widget(int index) const | 返回指定索引位置的标签页的内容窗口。 |
QString tabText(int index) const | 返回指定索引位置的标签页的标签文本。 |
void setTabText(int index, const QString &text) | 设置指定索引位置的标签页的标签文本。 |
QIcon tabIcon(int index) const | 返回指定索引位置的标签页的图标。 |
void setTabIcon(int index, const QIcon &icon) | 设置指定索引位置的标签页的图标。 |
void clear() | 移除所有标签页。 |
void setMovable(bool movable) | 设置标签页是否可移动。默认为可移动。 |
void setTabEnabled(int index, bool enable) | 设置指定索引位置的标签页是否可用。 |
bool isTabEnabled(int index) const | 返回指定索引位置的标签页是否可用。 |
int indexOf(QWidget *page) const | 返回指定内容窗口所在的标签页的索引。 |
QWidget *widget(const QString &label) const | 返回具有指定标签文本的标签页的内容窗口。 |
这些方法可以帮助你在 QTabWidget 中动态地管理标签页,设置标签文本、图标,以及进行标签页的切换和管理。
1.1 重复窗体分页
重复窗体的使用广泛应用于标签页克隆,例如一些远程SSH工具每次打开标签都是一个重复的交互环境,唯一不同的只是IP地址的变化,对于这些重复打开的标签页面就可以使用此分页来解决。
首先实现如下窗体布局,布局中空白部分是一个TabWidget分页组件,下方是一个PushButton按钮,当用户点击按钮时,自动将Dialog窗体追加到TabWidget组件中,如下图;

首先读者需要新建一个名叫FormDoc.ui的标准对话框,并在FormDoc构造函数中对该窗体进行初始化,如下代码则是自定义 FormDoc 类的实现,该类继承自 QWidget。在构造函数中,创建了垂直布局管理器 QVBoxLayout,并设置了一些边距和间距。然后,通过 setLayout 将这个布局管理器应用到 FormDoc 类的对象上。
在构造函数中,通过 parentWidget() 获取了父窗口指针,并通过强制类型转换将其转为 MainWindow* 类型。接着,通过调用 GetTableNumber() 方法获取了选中标签的索引,然后将其输出到控制台。此处的GetTableNumber()是父类中的函数,主要用于返回当前TabWidget组件的下标。
#include "formdoc.h"
#include "ui_formdoc.h"
#include "mainwindow.h"#include <QVBoxLayout>
#include <iostream>FormDoc::FormDoc(QWidget *parent) :QWidget(parent),ui(new Ui::FormDoc)
{ui->setupUi(this);QVBoxLayout *Layout = new QVBoxLayout();Layout->setContentsMargins(2,2,2,2);Layout->setSpacing(2);this->setLayout(Layout);// 获取父窗口指针MainWindow *parWind = (MainWindow*)parentWidget();// 获取选中标签索引QString ref = parWind->GetTableNumber();std::cout << ref.toStdString().data() << std::endl;
}FormDoc::~FormDoc()
{delete ui;
}
接着来看下MainWindow主窗体中是如何实现创建窗体的,当用户点击PushButton按钮时,首先new FormDoc新建一个空的窗体,并通过 addTab 方法将 FormDoc 实例添加到 QTabWidget 中,设置了选项卡的显示文本为 IP 地址("192.168.1.x")以及对应的图标。然后,通过 setCurrentIndex 将新建的选项卡设置为当前选中,并通过 setVisible(true) 确保 QTabWidget 是可见的。
另外,该主窗口还实现了一个槽函数 on_tabWidget_tabCloseRequested,当某个选项卡被关闭时触发。在这个槽函数中,首先获取被关闭的选项卡对应的 QWidget 指针,然后调用 close 方法关闭选项卡。需要注意的是,如果在关闭选项卡时需要执行一些清理工作,可以在 FormDoc 类的析构函数中进行相应的处理。
void MainWindow::on_pushButton_clicked()
{// 新建选项卡FormDoc *ptr = new FormDoc(this);// 关闭时自动销毁ptr->setAttribute(Qt::WA_DeleteOnClose);int cur = ui->tabWidget->addTab(ptr,QString::asprintf(" 192.168.1.%d",ui->tabWidget->count()));ui->tabWidget->setTabIcon(cur,QIcon(":/image/1.ico"));ui->tabWidget->setCurrentIndex(cur);ui->tabWidget->setVisible(true);
}// 关闭Tab时执行
void MainWindow::on_tabWidget_tabCloseRequested(int index)
{if (index<0)return;QWidget* aForm=ui->tabWidget->widget(index);aForm->close();
}
程序运行后读者可以点击创建窗体按钮,每次点击都会创建一个独立的新窗体,如下图所示;

1.2 独立窗体分页
在1.1节中,笔者所介绍的方法仅用于重复功能页面的创建,而有时我们需要让不同的窗口展示不同的功能,此时就需要实现多窗体,通过ToolBar与TabWidget组件的配合可以很好的实现多窗体的应用,如下图通过ToolBar配置一个按钮组件并初始化图标。

接着对窗体中的菜单栏依次绑定一个名称,其中名称使用action开头,如下图所示;

接着我们分别创建三个与之对应的Dialog对话框,其中actionMain对应formmain.ui、actionOption对应到formoption.ui、actionCharts对应到formcharts.ui上面,当首页按钮被点击后,在MainWindow中执行如下操作,首先判断窗体是否打开了,如果打开了则不允许继续打开新的,而如果没有被打开,那么我们就新建一个窗口,并设置到TabWidget上面,其代码如下所示;
// 首页菜单创建
void MainWindow::on_actionMain_triggered()
{int tab_count = ui->tabWidget->count();int option_count = 0;for(int x=0; x < tab_count; x++){// 获取出每个菜单的标题QString tab_name = ui->tabWidget->tabText(x);if(tab_name == "首页菜单")option_count = option_count + 1;}if(option_count < 1){FormMain *ptr = new FormMain(this); // 新建选项卡ptr->setAttribute(Qt::WA_DeleteOnClose); // 关闭时自动销毁int cur=ui->tabWidget->addTab(ptr,QString::asprintf("首页菜单"));ui->tabWidget->setTabIcon(cur,QIcon(":/image/1.ico"));ui->tabWidget->setCurrentIndex(cur);ui->tabWidget->setVisible(true);}
}
系统设置页面同理,这里我们规定系统设置页面也只能打开一个,其代码如下所示;
// 创建系统设置菜单
void MainWindow::on_actionOption_triggered()
{int tab_count = ui->tabWidget->count();int option_count = 0;for(int x=0; x < tab_count; x++){// 获取出每个菜单的标题QString tab_name = ui->tabWidget->tabText(x);if(tab_name == "系统设置")option_count = option_count + 1;}// 判断首页菜单是否只有一个,可判断标签个数来识别if(option_count < 1){FormOption *ptr = new FormOption(this);ptr->setAttribute(Qt::WA_DeleteOnClose);int cur = ui->tabWidget->addTab(ptr,QString::asprintf("系统设置"));ui->tabWidget->setTabIcon(cur,QIcon(":/image/2.ico"));ui->tabWidget->setCurrentIndex(cur);ui->tabWidget->setVisible(true);}
}
最后一个是图形绘制按钮,该按钮我们让其可以弹出多个,此处就不再限制弹出数量,只要点击按钮就新建一个并追加到TabWidget中,代码如下所示;
// 绘图页面的弹出
void MainWindow::on_actionCharts_triggered()
{FormCharts *ptr = new FormCharts(this);ptr->setAttribute(Qt::WA_DeleteOnClose);int cur = ui->tabWidget->addTab(ptr,QString::asprintf("图形绘制"));ui->tabWidget->setTabIcon(cur,QIcon(":/image/3.ico"));ui->tabWidget->setCurrentIndex(cur);ui->tabWidget->setVisible(true);
}
运行后读者可依次点击不同的按钮实现子窗体的创建,如下图所示;

相关文章:
C++ Qt开发:TabWidget实现多窗体功能
Qt 是一个跨平台C图形界面开发库,利用Qt可以快速开发跨平台窗体应用程序,在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置,实现图形化开发极大的方便了开发效率,本章将重点介绍TabWidget标签组件的常用方法及灵活运用。 Q…...
【轻量化篇】YOLOv8改进实战 | 更换主干网络 Backbone 之 RepGhostnet,重参数化实现硬件高效的Ghost模块
YOLOv8专栏导航:点击此处跳转 前言 轻量化网络设计是一种针对移动设备等资源受限环境的深度学习模型设计方法。下面是一些常见的轻量化网络设计方法: 网络剪枝:移除神经网络中冗余的连接和参数,以达到模型压缩和加速的目的。分组卷积:将卷积操作分解为若干个较小的卷积操…...
【STM32工具篇】使用CLion开发STM32
本文主要记录使用CLion开发STM32,并调试相关功能 使用的CLion版本:2023.3.1 CLion嵌入式配置教程:STM32CubeMX项目 |CLion 文档 (jetbrains.com) OpenOCD官网下载:Download OpenOCD for Windows (gnutoolchains.com) GNU ARM工…...
elementui中的el-table,当使用fixed属性时,table主体会遮挡住滚动条的大半部分,导致很难选中。
情况: 解决: el-table加个类,这里取为class"table" 然后是样式部分: <style scoped lang"scss"> ::v-deep.table {// 滚动条高度调整::-webkit-scrollbar {height: 15px;}// pointer-events 的基本信…...
鸿蒙端H5容器化建设——JSB通信机制建设
1. 背景 2023年鸿蒙开发者大会上,华为宣布为了应对国外技术封锁的潜在风险,2024年的HarmonyOS NEXT版本中将不再兼容Android,并推出鸿蒙系统以及其自研的开发框架,形成开发生态闭环。同时,在更高维度上华为希望将鸿蒙…...
数据管理平台Splunk Enterprise本地部署结合内网穿透实现远程访问
文章目录 前言1. 搭建Splunk Enterprise2. windows 安装 cpolar3. 创建Splunk Enterprise公网访问地址4. 远程访问Splunk Enterprise服务5. 固定远程地址 前言 Splunk Enterprise是一个强大的机器数据管理平台,可帮助客户分析和搜索数据,以及可视化数据…...
MaBatis使用`ResultMap`标签手动映射详解使用
文章目录 MaBatis使用ResultMap标签手动映射详解使用1、MyBatis只能自动维护库表”列名“与”属性名“相同时的对应关系,二者不同时无法自动ORM,如下:2、在SQL中使用 as 为查询字段添加列别名,以匹配属性名:但是如果我…...
openstack-keystone服务
文章目录 keystone服务安装和配置先决条件安装并配置组件运行以下命令来安装包。编辑文件 /etc/keystone/keystone.conf 并完成如下动作:初始化身份认证服务的数据库:初始化Fernet keys:Bootstrap the Identity service: 配置 Apache HTTP 服…...
大数据HCIE成神之路之数据预处理(3)——数值离散化
数值离散化 1.1 无监督连续变量的离散化 – 聚类划分1.1.1 实验任务1.1.1.1 实验背景1.1.1.2 实验目标1.1.1.3 实验数据解析 1.1.2 实验思路1.1.3 实验操作步骤1.1.4 结果验证 1.2 无监督连续变量的离散化 – 等宽划分1.2.1 实验任务1.2.1.1 实验背景1.2.1.2 实验目标1.2.1.3 实…...
stm32 寄存器、地址、位带操作
存储器区域功能划分 4GB 的地址空间中,ARM 已经粗线条的平均分成了 8 个块,每块 512MB,每个块也都规定了用途,具体分类见表格 6-1。每个块的大小都有 512MB,显然这是非常大的,芯片厂商在每个块的范围内设计…...
记录 | gdb使用backward-cpp来美化调试log
# 在当前工程目录下 git clone https://github.com/bombela/backward-cpp.git 编辑CMakeList.txt cmake_minimum_required(VERSION 3.15)project(exampleproj LANGUAGES CXX)add_subdirectory(backward-cpp)add_executable(main main.cpp)target_sources(main PUBLIC ${BACKW…...
EasyExcel模板导出(行和列自动合并)
1.需求背景: ①需要从第三方获取数据,第三方接口有两个参数,开始时间和结束时间 ②获取回来的数据并没有入库,所以不能通过数据库将数据归类统计,excel合并大概的流程是判断上一行或者左右相邻列是否相同,然后进行合并,所以不能是零散的数据且客户要求每一个自治区和每一个航站…...
EOCR-i3MZ/iFMZ施耐德漏电保护继电器产品简介
EOCR-i3MZ/iFMZ是施耐德EOCR的新一代电子式电动机保护器产品,具有过电流、欠电流、缺相、逆相、堵转、失速、三相不平衡、接地等保护功能。EOCR-i3MZ/iFMZ是通讯型产品,提供Modbus RTU通讯协议,RS485接口。 为方便设备维护人员排查电动机的故…...
golang开发--beego入门
Beego 是一个基于 Go 语言的开源框架,用于构建 Web 应用程序和 API。它采用了一些常见的设计模式,以提高开发效率、代码可维护性和可扩展性。 一,MVC设计模式 Beego 框架采用了经典的 MVC(Model-View-Controller)设计…...
python调取一欧易API并写一个比特币均线交易策略
比特币均线交易策略是一种基于比特币价格的移动均线的交易策略。它通过计算不同时间段的移动均线来确定买入和卖出点。 具体步骤如下: 确定要使用的均线。常用的均线包括5日、10日、20日、50日和200日均线。较短的均线可以更快地反应价格变动,而较长的均…...
使用arthas排查请求超时问题
现象 客户端调用服务时间出现偶尔超时现象 排查 因为服务已开启arthas,使用trace命令监控 $ trace com.lizz slowfun #cost > 1000 -n 10 监控com.lizz类中的slowfun方法,输出用时超过1000ms的记录,记录10条 Press CtrlC to abort. Aff…...
SAP ABAP EXCEL 下载模板并导入
具体参考: ABAP EXCEL 下载摸板 获取数据模板文件路径 FORM fm_get_filepath .DATA: lv_filename TYPE string,lv_path TYPE string,lv_fullpath TYPE string,lv_title TYPE string.co_objid ZMMRP002.CONCATENATE co_objid - sy-datum sy-uzeit INTO l…...
Map集合体系
Map集合的概述 Map集合是一种双列集合,每个元素包含两个数据。 Map集合的每个元素的格式:keyvalue(键值对元素)。 Map集合也被称为“键值对集合”。 Map集合的完整格式:{key1value1 , key2value2 , key3value3 , ...} Map集合的使用场景…...
速度与稳定性的完美结合:深入横测ToDesk、TeamViewer和AnyDesk
文章目录 前言什么是远程办公?远程办公的优势 远程办公软件横测对象远程软件的注册&安装ToDeskTeamViewerAnyDesk 各场景下的实操体验1.办公文件传输及丢包率2.玩游戏操作延迟、稳定3.追剧画质流畅度、稳定4.临时技术支持SOS模式 收费情况与设备连接数总结 前言…...
数据库系统的结构
数据库系统的结构 1 数据抽象1.1 物理层1.2 逻辑层1.3 视图层 2 实例和模式3 数据独立性4 数据模型4.1 基于对象的逻辑模型4.2 基于记录的逻辑模型4.3 基于记录的物理模型 5 数据库语言5.1 数据定义语言 DDL5.2 数据操纵语言 DML 6 事务7 存储管理器8 数据库系统的总体结构 1 数…...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
怎么让Comfyui导出的图像不包含工作流信息,
为了数据安全,让Comfyui导出的图像不包含工作流信息,导出的图像就不会拖到comfyui中加载出来工作流。 ComfyUI的目录下node.py 直接移除 pnginfo(推荐) 在 save_images 方法中,删除或注释掉所有与 metadata …...
LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)
在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...
【UE5 C++】通过文件对话框获取选择文件的路径
目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 ,这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器,右键点击 .uproject 文件,选择 "Generate Visual Studio project files",重…...
Mysql故障排插与环境优化
前置知识点 最上层是一些客户端和连接服务,包含本 sock 通信和大多数jiyukehuduan/服务端工具实现的TCP/IP通信。主要完成一些简介处理、授权认证、及相关的安全方案等。在该层上引入了线程池的概念,为通过安全认证接入的客户端提供线程。同样在该层上可…...
Python爬虫实战:研究Restkit库相关技术
1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的有价值数据。如何高效地采集这些数据并将其应用于实际业务中,成为了许多企业和开发者关注的焦点。网络爬虫技术作为一种自动化的数据采集工具,可以帮助我们从网页中提取所需的信息。而 RESTful API …...
深度解析:etcd 在 Milvus 向量数据库中的关键作用
目录 🚀 深度解析:etcd 在 Milvus 向量数据库中的关键作用 💡 什么是 etcd? 🧠 Milvus 架构简介 📦 etcd 在 Milvus 中的核心作用 🔧 实际工作流程示意 ⚠️ 如果 etcd 出现问题会怎样&am…...
