【Qt笔记】QStackedWidget控件详解

目录

引言

一、基础功能

二、属性设置

2.1 属性介绍

2.2 代码示例 

2.3 代码解析

三、常用API

3.1 添加子部件

3.2 插入子部件

3.3 移除子部件

3.4 设置当前页面索引值

3.5 设置当前显示子部件

3.6 返回索引处子部件指针

3.7 返回子部件索引值

四、信号与槽

4.1 currentChanged

4.2 widgetRemoved

五、应用示例

5.1 代码 

5.2 实现效果

5.3 代码解析

结语


引言

QStackedWidget是 Qt 框架中的一个非常有用的控件,它允许你堆叠多个窗口部件(widgets),但一次只显示一个。这种机制非常适合于实现向导、多视图应用程序、选项卡界面(虽然它没有内置的选项卡头)以及表单向导等场景。通过改变当前索引,可以轻松地切换显示的窗口部件。

 

一、基础功能

QStackedWidget是Qt框架中的一个容器控件,用于在同一区域内动态地堆叠和显示不同的子部件(如窗口、对话框、页面等)。它一次只显示一个子部件,但允许开发者通过编程方式轻松地在这些子部件之间切换。

  • 页面堆叠:QStackedWidget通过堆叠的方式管理多个页面(子部件),每个页面都有一个唯一的索引值。只有当前索引对应的页面是可见的,其他页面则会被隐藏。
  • 动态切换:开发者可以通过设置当前索引或当前子部件来动态地切换显示的页面。这种切换是即时的,且可以响应各种事件或用户操作。
  • 灵活布局:QStackedWidget本身并不提供布局管理功能,但它可以与其他布局管理器(如QVBoxLayout、QHBoxLayout等)结合使用,以实现复杂的界面布局。

二、属性设置

2.1 属性介绍

虽然QStackedWidget没有像QWidget那样众多的属性需要直接设置,但它通过其API函数提供了丰富的控制手段。以下是一些与属性设置相关的要点:

  • 当前页面索引(currentIndex):这是一个只读属性,用于获取当前显示的页面的索引值。虽然不能直接设置该属性,但可以通过调用setCurrentIndex()函数来改变当前页面。
  • 当前页面(currentWidget):这同样是一个只读属性,返回当前显示的页面的指针。同样地,不能直接设置该属性,但可以通过setCurrentWidget()函数来改变当前页面。
  • 页面计数(count):这是一个只读属性,返回QStackedWidget中子部件的数量。这有助于在编程时遍历或检查子部件。

2.2 代码示例 

以下是为QStackedWidget的currentIndex、currentWidget和count属性提供代码示例的方式。需要注意的是,由于currentIndex和currentWidget是只读属性,我们不能直接“设置”它们,但可以通过调用相关函数来改变它们所代表的状态。

#include <QApplication>  
#include <QStackedWidget>  
#include <QPushButton>  
#include <QVBoxLayout>  
#include <QWidget>  
#include <QLabel>  
  
int main(int argc, char *argv[]) {  
    QApplication app(argc, argv);  
  
    // 创建主窗口  
    QWidget window;  
    QVBoxLayout *layout = new QVBoxLayout(&window);  
  
    // 创建QStackedWidget  
    QStackedWidget *stackedWidget = new QStackedWidget;  
  
    // 添加几个页面到QStackedWidget  
    QWidget *page1 = new QWidget;  
    QLabel *label1 = new QLabel("Page 1", page1);  
    QVBoxLayout *page1Layout = new QVBoxLayout(page1);  
    page1Layout->addWidget(label1);  
  
    QWidget *page2 = new QWidget;  
    QLabel *label2 = new QLabel("Page 2", page2);  
    QVBoxLayout *page2Layout = new QVBoxLayout(page2);  
    page2Layout->addWidget(label2);  
  
    QWidget *page3 = new QWidget;  
    QLabel *label3 = new QLabel("Page 3", page3);  
    QVBoxLayout *page3Layout = new QVBoxLayout(page3);  
    page3Layout->addWidget(label3);  
  
    stackedWidget->addWidget(page1);  
    stackedWidget->addWidget(page2);  
    stackedWidget->addWidget(page3);  
  
    // 将QStackedWidget添加到主窗口布局  
    layout->addWidget(stackedWidget);  
  
    // 创建按钮来切换页面  
    QPushButton *prevButton = new QPushButton("Previous");  
    QPushButton *nextButton = new QPushButton("Next");  
    QHBoxLayout *buttonLayout = new QHBoxLayout;  
    buttonLayout->addWidget(prevButton);  
    buttonLayout->addWidget(nextButton);  
    layout->addLayout(buttonLayout);  
  
    // 初始时禁用“Previous”按钮  
    prevButton->setEnabled(false);  
  
    // 连接信号与槽以切换页面  
    QObject::connect(nextButton, &QPushButton::clicked, [stackedWidget, prevButton]() {  
        int currentIndex = stackedWidget->currentIndex();  
        if (currentIndex < stackedWidget->count() - 1) {  
            stackedWidget->setCurrentIndex(currentIndex + 1);  
            prevButton->setEnabled(true);  
        }  
    });  
  
    QObject::connect(prevButton, &QPushButton::clicked, [stackedWidget]() {  
        int currentIndex = stackedWidget->currentIndex();  
        if (currentIndex > 0) {  
            stackedWidget->setCurrentIndex(currentIndex - 1);  
            if (currentIndex == 1) {  
                // 在这个简单的例子中,我们总是启用“Previous”按钮  
                // 但在更复杂的应用中,你可能需要根据实际情况来决定是否禁用它  
            }  
        }  
    });  
  
    // 示例:打印当前页面索引和页面计数  
    qDebug() << "Initial current index:" << stackedWidget->currentIndex();  
    qDebug() << "Total page count:" << stackedWidget->count();  
  
    // 示例:通过currentWidget获取当前页面并打印其标签文本(假设标签是页面的直接子部件)  
    if (QLabel *currentLabel = stackedWidget->currentWidget()->findChild<QLabel*>()) {  
        qDebug() << "Current page label text:" << currentLabel->text();  
    }  
  
    window.setWindowTitle("QStackedWidget Example");  
    window.resize(400, 300);  
    window.show();  
    return app.exec();  
}

2.3 代码解析

在这个示例中:

  • 我们创建了一个QStackedWidget并向其中添加了三个页面。
  • 每个页面都是一个包含QLabel的QWidget。
  • 我们添加了两个按钮来在页面之间切换,并根据当前页面索引启用或禁用“Previous”按钮。
  • 使用qDebug()打印了初始的当前页面索引和页面总数,展示了如何访问这些只读属性。
  • 我们还展示了如何通过currentWidget()获取当前页面,并使用findChild<QLabel*>()查找并打印当前页面上QLabel的文本(注意:这种方法假设QLabel是页面的直接子部件,且页面上只有一个QLabel)。在实际应用中,你可能需要更复杂的逻辑来定位特定的子部件。

三、常用API

QStackedWidget提供了丰富的API函数,以便开发者能够灵活地管理和控制其包含的页面。以下是一些常用的API函数及其说明:

3.1 添加子部件

addWidget(QWidget *widget, int index = -1):向QStackedWidget中添加一个子部件。如果指定了索引(index),则子部件将被插入到该索引位置;如果未指定索引(或指定为-1),则子部件将被添加到末尾。

// 创建一个主窗口  
QWidget window;  
QVBoxLayout *layout = new QVBoxLayout(&window);  
  
// 创建一个QStackedWidget  
QStackedWidget *stackedWidget = new QStackedWidget;  
  
// 创建几个页面  
QWidget *page1 = new QWidget;  
QLabel *label1 = new QLabel("Page 1", page1);  
QVBoxLayout *page1Layout = new QVBoxLayout(page1);  
page1Layout->addWidget(label1);  
  
QWidget *page2 = new QWidget;  
QLabel *label2 = new QLabel("Page 2", page2);  
QVBoxLayout *page2Layout = new QVBoxLayout(page2);  
page2Layout->addWidget(label2);  

QWidget *page3 = new QWidget;  
QLabel *label3 = new QLabel("Page 3", page3);  
QVBoxLayout *page3Layout = new QVBoxLayout(page3);  
page3Layout->addWidget(label3);  
  
// 使用addWidget添加页面到末尾  
stackedWidget->addWidget(page1);  
stackedWidget->addWidget(page2);

3.2 插入子部件

insertWidget(int index, QWidget *widget):在指定索引处插入一个子部件。如果索引超出当前范围,则子部件将被添加到末尾。

// 使用insertWidget在指定索引处插入页面  
stackedWidget->insertWidget(1, page3); // 这将page3插入到page1和page2之间  

3.3 移除子部件

removeWidget(QWidget *widget):从QStackedWidget中移除一个子部件。子部件本身不会被删除,只是从布局中移除,从而被隐藏。

// 假设现在想要移除page2  
stackedWidget->removeWidget(page2);  

3.4 设置当前页面索引值

setCurrentIndex(int index):设置当前显示的页面的索引值。如果索引值超出范围,则不会改变当前页面。

// 设置当前页面索引  
stackedWidget->setCurrentIndex(0); // 显示page1

3.5 设置当前显示子部件

setCurrentWidget(QWidget *widget):设置当前显示的子部件。如果指定的子部件已经存在于QStackedWidget中,则它将成为当前页面;如果不存在,则什么也不会发生。

3.6 返回索引处子部件指针

widget(int index):返回指定索引处的子部件的指针。如果索引超出范围,则返回nullptr。

// 获取并显示指定索引处的子部件  
QWidget *currentPage = stackedWidget->widget(0);  
if (currentPage) {  
    QLabel *currentLabel = currentPage->findChild<QLabel*>();  
    if (currentLabel) {  
        qDebug() << "Current page label text:" << currentLabel->text();  
    }  
} 

3.7 返回子部件索引值

indexOf(QWidget *widget):返回子部件在QStackedWidget中的索引值。如果子部件不存在于QStackedWidget中,则返回-1。

// 获取子部件在QStackedWidget中的索引  
int index = stackedWidget->indexOf(page3);  
qDebug() << "Index of page3:" << index; // 应该输出1,除非在添加/移除后修改了索引

四、信号与槽

QStackedWidget还提供了几个信号,以便在页面切换或页面被移除时通知开发者。这些信号可以与槽函数(即回调函数)连接,以执行特定的操作。

4.1 currentChanged

currentChanged(int index):当当前显示的页面改变时发射。参数index是新显示的页面的索引值。

// 连接currentChanged信号  
connect(stackedWidget, &QStackedWidget::currentChanged, this, [=](int index) {  
    qDebug() << "Current page changed to index:" << index;  
}); 

4.2 widgetRemoved

widgetRemoved(int index):当一个小部件(页面)从QStackedWidget中移除时发射。参数是被移除的小部件的索引值。

// 连接widgetRemoved信号  
connect(stackedWidget, &QStackedWidget::widgetRemoved, this, [=](int index) {  
    qDebug() << "Widget removed from index:" << index;  
}); 

五、应用示例

5.1 代码 

以下是一个简化的向导示例,展示了如何使用QStackedWidget来实现一个多步骤的向导界面。

#include <QApplication>  
#include <QStackedWidget>  
#include <QLabel>  
#include <QPushButton>  
#include <QVBoxLayout>  
#include <QHBoxLayout>  
  
class Wizard : public QWidget {  
    Q_OBJECT  
public:  
    Wizard(QWidget *parent = nullptr) : QWidget(parent) {  
        auto *stackedWidget = new QStackedWidget(this);  
  
        // 创建向导页面  
        QWidget *page1 = createPage("Welcome", "This is the first page of the wizard.");  
        QWidget *page2 = createPage("Name", "Enter your name:");  
        QWidget *page3 = createPage("Finish", "Thank you! You have completed the wizard.");  
  
        stackedWidget->addWidget(page1);  
        stackedWidget->addWidget(page2);  
        stackedWidget->addWidget(page3);  
  
        // 导航按钮  
        auto *backButton = new QPushButton("Back", this);  
        auto *nextButton = new QPushButton("Next", this);  
  
        // 禁用“后退”按钮在第一页  
        backButton->setEnabled(false);  
  
        // 布局  
        auto *mainLayout = new QVBoxLayout(this);  
        mainLayout->addWidget(stackedWidget);  
  
        auto *buttonLayout = new QHBoxLayout();  
        buttonLayout->addWidget(backButton);  
        buttonLayout->addWidget(nextButton);  
        mainLayout->addLayout(buttonLayout);  
  
        // 连接信号和槽  
        connect(nextButton, &QPushButton::clicked, [=]() {  
            if(nextButton->text() == "Finish")
            {
                this->close();
            }
            int currentIndex = stackedWidget->currentIndex();  
            if (currentIndex < stackedWidget->count() - 1) {  
                stackedWidget->setCurrentIndex(currentIndex + 1);  
                if (currentIndex == 1) { // 假设第二页是最后一页需要处理的  
                    // 在这里处理用户输入,如验证名称等  
                    // ...  
                }  
                backButton->setEnabled(true);  
                if (currentIndex == stackedWidget->count() - 2) {  
                    // 在最后一页设置“下一步”按钮文本
                    nextButton->setText("Finish");   
                }  
            }  
        });  
  
        connect(backButton, &QPushButton::clicked, [=]() {  
            int currentIndex = stackedWidget->currentIndex();  
            if (currentIndex > 0) {  
                stackedWidget->setCurrentIndex(currentIndex - 1);  
                backButton->setEnabled(currentIndex > 0);  
                if (currentIndex == 1) {  
                    nextButton->setText("Next");  
                    nextButton->setEnabled(true);  
                }  
            }  
        });  
  
        // 初始显示第一步  
        stackedWidget->setCurrentIndex(0);  
    }  
  
private:  
    QWidget *createPage(const QString &title, const QString &text) {  
        QWidget *page = new QWidget();  
        QLabel *label = new QLabel(text, page);  
        QVBoxLayout *layout = new QVBoxLayout(page);  
        layout->addWidget(new QLabel(title, page));  
        layout->addWidget(label);  
        return page;  
    }  
};  
  
// ... (main函数和QApplication的实例化)

5.2 实现效果

 

5.3 代码解析

在这个示例中,我们创建了一个简单的向导,它有三个页面:欢迎页、名称输入页和完成页。通过createPage辅助函数,我们简化了页面创建的过程。导航按钮根据当前页面的索引启用或禁用,并在最后一页时将“下一步”按钮的文本更改为“完成”并且在判断识别到文本更改为”Finsh“,并点击时,关闭窗口。这个示例展示了如何在页面切换时执行简单的逻辑,并管理按钮的启用/禁用状态。 

结语

QStackedWidget是Qt框架中一个非常实用的控件,它允许开发者在一个固定区域内堆叠多个子窗口或页面,并通过切换来显示不同的内容。通过使用QStackedWidget,我们可以轻松地创建多页的用户界面,如向导、选项卡等。希望本文的详细解析和示例代码能够帮助你更好地理解和使用QStackedWidget。 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/884192.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代码随想录Day 58|拓扑排序、dijkstra算法精讲,题目:软件构建、参加科学大会

提示&#xff1a;DDU&#xff0c;供自己复习使用。欢迎大家前来讨论~ 文章目录 图论part08**拓扑排序精讲**题目&#xff1a;117. 软件构建拓扑排序的背景解题思路&#xff1a;模拟过程 **dijkstra&#xff08;朴素版&#xff09;精讲**题目&#xff1a;47. 参加科学大会解题思…

OpenCV视频I/O(5)视频采集类VideoCapture之从视频流中获取下一帧的函数grab()的使用

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 从视频文件或捕获设备中抓取下一帧。 grab() 函数是 OpenCV 中 VideoCapture 类的一个成员函数&#xff0c;用于从视频流中获取下一帧而不立即检…

Android Studio 真机USB调试运行频繁掉线问题

一、遇到问题 Android Studio使用手机运行项目时&#xff0c;总是频繁掉线&#xff0c;连接很不稳定&#xff0c;动不动就消失&#xff0c;基本上无法使用 二、问题出现原因 1、硬件问题&#xff1a;数据线 换条数据线试试&#xff0c;如果可以&#xff0c;那就是数据线的…

element plus block报错

解决&#xff1a; ::v-deep input[aria-hidden"true"] {display: none !important }

9.3 Linux_I/O_文件I/O相关函数

打开与关闭 1、打开文件 int open(const char *pathname, int flags); int open(const char *pathname, int flags, mode_t mode);返回值&#xff1a;成功返回文件描述符&#xff0c;失败返回EOF pathname&#xff1a;文件路径 flags&#xff1a;标志&#xff0c;其中O_RDO…

《面向对象是怎样工作的》笔记

6、1、在面向对象的世界中&#xff0c;我们需要事先为所有的行动准备好方法并通过消息传递来调用方法&#xff0c;这样事物才会开始运作。 2、实际上&#xff0c;类、继承和多态应该被明确定义为能提高软件的可维护性和可重用行的结构。类将变量和子程序汇总在一起&#xff0c…

Vue 技术入门 day1 模版语法、数据绑定、事件处理、计算属性与监视、class和style绑定、条件渲染v-if/v-show、列表渲染v-for

目录 1.Vue 核心 1.1. Vue 简介 1.1.1 介绍与描述 1.1.2 Vue 的特点 1.2 模板语法 1.2.1 模板的分类 1.2.2 插值语法 1.2.3 指令语法 1.2.4 实例 1.3 数据绑定 1.3.1 单向数据绑定 1.3.2 双向数据绑定 1.3.3 MVVM 模型 1.3.4 data与el的2种写法 1.3.5 实例 1.3.…

信息安全工程师(25)网络安全体系框架主要组成和建设内容

一、主要组成 信息安全战略&#xff1a;确立组织的信息安全目标和方向&#xff0c;指导整个网络安全体系的建设和运营。信息安全政策和标准&#xff1a;制定和执行一系列信息安全政策、标准和规范&#xff0c;确保网络安全活动有法可依、有章可循。信息安全管理&#xff1a;包括…

网站建设中常见的网站后台开发语言有哪几种,各自优缺点都是什么?

市场上常见的网站后台开发语言有PHP、Python、JavaScript、Ruby、Java和.NET等。这些语言各有其独特的优缺点&#xff0c;适用于不同的开发场景和需求。以下是对这些语言的具体介绍&#xff1a; PHP 优点&#xff1a;PHP是一种广泛用于Web开发的动态脚本语言&#xff0c;特别适…

《论文阅读》 用于产生移情反应的迭代联想记忆模型 ACL2024

《论文阅读》 用于产生移情反应的迭代联想记忆模型 ACL2024 前言简介任务定义模型架构Encoding Dialogue InformationCapturing Associated InformationPredicting Emotion and Generating Response损失函数问题前言 亲身阅读感受分享,细节画图解释,再也不用担心看不懂论文啦…

成都睿明智科技有限公司赋能商家高效变现

在这个日新月异的数字时代&#xff0c;抖音电商正以不可阻挡之势崛起&#xff0c;成为众多品牌与商家竞相角逐的新战场。在这片充满机遇与挑战的蓝海中&#xff0c;成都睿明智科技有限公司如同一颗璀璨新星&#xff0c;凭借其专业的服务、创新的策略和敏锐的市场洞察&#xff0…

NLP 文本分类任务核心梳理

解决思路 分解为多个独立二分类任务将多标签分类转化为多分类问题更换 loss 直接由模型进行多标签分类 数据稀疏问题 标注更多数据&#xff0c;核心解决方案&#xff1a; 自己构造训练样本 数据增强&#xff0c;如使用 chatGPT 来构造数据更换模型 减少数据需求增加规则弥补…

[element-ui]记录对el-table表头样式的一些处理

1、表头换行 & 列表项换行 可用element-table组件自带的方法实现列标题换行的效果 2、小圆点样式

第五部分:5---三张信号表,信号表的系统调用

目录 信号的递达、未决、阻塞&#xff1a; 进程维护的三张信号表&#xff1a; 普通信号与实时信号的记录&#xff1a; 信号结构的系统调用&#xff1a; bolck表的系统调用&#xff1a; 实例&#xff1a;设置屏蔽信号集中的所有信号都频闭 pending表读取&#xff1a; 信号…

计算机网络——TCP/IP网络模型

1. TCP/IP网络模型有哪几层 对于同一台设备上的进程间通信&#xff0c;有很多种方式&#xff0c;比如管道、消息队列、共享内存、信号等。而对于不同设备上的进程间通信&#xff0c;就需要网络通信&#xff0c;而设备是多样性的&#xff0c;所以要兼容多种多样的设备&#xff…

STM32快速复习(十二)FLASH闪存的读写

文章目录 一、FLASH是什么&#xff1f;FLASH的结构&#xff1f;二、使用步骤1.标准库函数2.示例函数 总结 一、FLASH是什么&#xff1f;FLASH的结构&#xff1f; 1、FLASH简介 &#xff08;1&#xff09;STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分&…

Java每日面试题(JVM)(day15)

目录 Java对象内存布局markWord 数据结构JDK1.8 JVM 内存结构JDK1.8堆内存结构GC垃圾回收如何发现垃圾如何回收垃圾 JVM调优参数 Java对象内存布局 markWord 数据结构 JDK1.8 JVM 内存结构 程序计数器: 线程私有&#xff0c;记录代码执行的位置. Java虚拟机栈: 线程私有&#…

HarmonyOS鸿蒙系统开发应用程序,免费开源DevEco Studio开发工具

DevEco Studio 是华为为 HarmonyOS 和 OpenHarmony 开发者提供的官方集成开发环境&#xff08;IDE&#xff09;&#xff0c;它基于 IntelliJ IDEA Community 版本打造&#xff0c;提供了代码编辑、编译、调试、发布等一体化服务。 一、DevEco Studio支持系统 DevEco Studio支持…

Centos怎么执行脚本

方法一&#xff1a;切换到shell脚本所在的目录&#xff08;此时&#xff0c;称为工作目录&#xff09;执行shell脚本 cd /data/shell ./hello.sh 方法二&#xff1a;以绝对路径的方式去执行bash shell脚本 /data/shell/hello.sh 方法三&#xff1a;直接使用bash 或sh 来执行…

中国算力大会启幕,联想发布异构智算产业创新成果

9月27日&#xff0c;2024中国算力大会在河南郑州拉开帷幕。作为全球领先的算力基础设施和服务提供商&#xff0c;联想集团参会参展并携手异构智算产业联盟承办2024异构智算产业生态联盟技术论坛。 据「TMT星球」了解&#xff0c;论坛发布了新一代AI服务器、AI应用部署解决方案…