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

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

接着我们分别创建三个与之对应的Dialog对话框,其中actionMain对应formmain.uiactionOption对应到formoption.uiactionCharts对应到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);
}

运行后读者可依次点击不同的按钮实现子窗体的创建,如下图所示;

附件下载

TabWidget

C++ Qt开发:TabWidget实现多窗体功能的更多相关文章

  1. 初学Qt——vs2012开发环境下的窗体跳转

    最近接了份外快,要求使用vs+qt开发一个简单的数据管理系统.qt开发使用的语言是c++,然而c++只是大一第二学期有教过而已,基本也差不多忘光了,废话不多说,讲下今天遇到的问题吧 如标题所说,窗体跳 ...

  2. Qt开发:Windows 下进程间通信的可行桥梁:窗体消息SendMessage

    Qt开发:Windows 下进程间通信的可行桥梁:窗体消息 注:窗体消息仅适用于有窗口的进程,如果没有窗口是无法收到窗体消息的(哪怕是隐形的都可以),比如Qt中如果需要使用WindowsMessage ...

  3. 基于arm的嵌入式QT开发(课程设计)

    一. 项目要求 配置QT5.7基于x86及arm 等两种CPU架构的调试及开发环境: 移植arm编译后的QT5.7及屏幕校准工具tslib1.4至CORTEX ARM9实验平台: 开发基于QT5.7的 ...

  4. Qt开发环境的建立

    在建立开发环境之前,先来了解一下Qt是什么以及它的历史变迁.Qt是一个1991年由Qt Company开发的跨平台C++图形用户界面应用程序开发框架.它既可以开发GUI程序,也可用于开发非GUI程序, ...

  5. Qt开发环境中使用报表控件FastReport遇到的一些问题(一)

    FastReport是一款优秀的报表控件,由俄罗斯开发,国内有代理商.Qt环境下可实现报表功能的还有一款叫NCReport,也是收费控件,比较来比较去还是觉得前者功能强点.网上讲解此控件在Qt中使用的 ...

  6. OpenCV+QT开发环境(一):Windows环境

    最近在学习openCV的开发.在搭建开发环境的时候,着实废了不少功夫,找了大量的文章资料.其实主要的开发还是在linux系统上的openCV,但是为了方便,我还是在windows上也搭建了开发环境,这 ...

  7. QT开发pjsip的VOIP,A8平台运行

    QT开发pjsip的VOIP 开发环境 平台:A8 环境:Linux-3.0.8 实现功能:使用QT开发VOIP进行初始化.拨号.挂起 测试工具:minisipserver服务器 效果 界面: min ...

  8. 【应用笔记】【AN005】Qt开发环境下基于RS485的4-20mA电流采集

    简介 4-20mA电流环具有广泛的应用前景,在许多行业中都发挥着重要作用.本文主要介绍在Qt开发环境下基于RS485实现4-20mA电流采集,实现WINDOWS平台对数据的采集.分析及显示. 系统组成 ...

  9. QT开发之旅三串口设备调试工具

    这里首先说明一下,这个为什么叫串口设备调试工具而不是串口调试工具,是因为这个工具比网络上的串口调试工具多出了一些真实需要的用来调试设备的功能,首先一点就是大部分的串口调试工具收到数据都是立即返回,这样 ...

  10. 使用cocoa捕获dock栏中的“退出”事件,解决qt开发的应用程序退出异常的问题

    最近在移植一个QT开发的应用程序到mac平台,由于我们的应用在退出时需要释放一些资源,不然在mac系统会报崩溃事件,但是当用户使用dock栏上面的退出功能时,没有捕获到这个退出事件,导致无法正常退出. ...

随机推荐

  1. 杰哥教你面试之一百问系列:java多线程

    java多线程是java面试中的高频问题,如何才能在面试中脱颖而出呢?熟读这里的一百个java多线程面试问题即可. 1. 什么是线程?什么是进程? 回答: 线程是操作系统能够进行调度的最小执行单位,它 ...

  2. 数据api接口就是应用集成吗?

    ​ 数据 API 接口和应用集成是两个不同的概念,但是它们之间有一定的联系.数据 API 接口是一种用于访问和传输数据的标准化接口,而应用集成则是将不同的应用程序和系统整合在一起,实现数据和业务流程的 ...

  3. CDC一键入湖:当 Apache Hudi DeltaStreamer 遇见 Serverless Spark

    Apache Hudi的DeltaStreamer是一种以近实时方式摄取数据并写入Hudi表的工具类,它简化了流式数据入湖并存储为Hudi表的操作,自 0.10.0 版开始,Hudi又在DeltaSt ...

  4. 运用手机运营商二要素Api接口,守护您的账户和隐私,让您安心使用!

    随着移动互联网的普及,我们的生活离不开手机,手机成为了我们生活中不可或缺的一部分.但是随着移动支付的普及,手机支付在我们的生活中也变得越来越重要.手机支付是一种方便快捷的支付方式,但是也存在一些安全隐 ...

  5. 利用BGP Anycast 实现DNS 服务的高可用测试

    一.背景     根据当前某公司内部生产系统容器平台架构设计,在各生产线边缘机房部署容器平台,与数据中心容器平台形成纵向冗余,在此情况下,传统部署在数据中心机房的DNS系统成为容器平台业务服务的短板, ...

  6. 如何保持 SSH 会话不中断?

    哈喽大家好,我是咸鱼 不知道小伙伴们有没有遇到过下面的情况: 使用终端(XShell.secureCRT 或 MobaXterm 等)登录 Linux 服务器之后如果有一段时间没有进行交互,SSH 会 ...

  7. Unity 游戏开发、02 基础篇 | 知识补充、简单使用动画、动画状态机

    前置笔记(由浅入深) Unity 游戏开发.01 基础篇 2 场景操作 3D场景 Q 手型工具(鼠标中键):上下左右移动场景 ALT + 鼠标左键:以视图为中心旋转 鼠标右键:以观察者为中心旋转 SH ...

  8. .NET微服务系列之Saga分布式事务案例实践

    自从Wing正式发布以后,很多童鞋反馈对Saga分布式事务比较感兴趣,今天就跟大家分享一下"跨行转账"的分布式事务实践案例,入门使用教程请自行前往Wing官方文档. 假设自己名下有 ...

  9. JAVA图搜索算法之DFS-BFS

    图算法DFS与BFS BFS和DFS代表对图进行遍历,即搜索的算法,搜索算法中常用的只要有两种算法:深度优先遍历(Depth-First-Search : DFS)和广度优先遍历(Breadth-Fi ...

  10. 接口开放太麻烦?试试阿里云API网关吧

    前言 我在多方合作时,系统间的交互是怎么做的?这篇文章中写过一些多方合作时接口的调用规则和例子,然而,接口开放所涉及的安全.权限.监控.流量控制等问题,可不是简简单单就可以解决的,这一般需要专业的开放 ...