Qt-QStackedWidget

一、基本概念

1.1 什么是 QStackedWidget

QStackedWidget 是 Qt 中的一个容器控件,它可以包含多个子控件(页面),但一次只显示其中一个。类似于一叠卡片,只有最上面的卡片可见。

1.2 主要特点

  • 多个页面共享同一显示区域

  • 一次只显示一个页面

  • 可通过索引或指针切换页面

  • 常用于实现标签页、向导界面等

二、Qt6 中的语法和 API

2.1 基本 API

cpp 复制代码
#include <QStackedWidget>

// 创建
QStackedWidget *stackedWidget = new QStackedWidget(parent);

// 添加页面
int index = stackedWidget->addWidget(widget);
int index = stackedWidget->insertWidget(index, widget);

// 切换页面
stackedWidget->setCurrentIndex(index);        // 通过索引
stackedWidget->setCurrentWidget(widget);      // 通过指针

// 获取信息
int currentIndex = stackedWidget->currentIndex();
QWidget *currentWidget = stackedWidget->currentWidget();
int count = stackedWidget->count();
QWidget *widget = stackedWidget->widget(index);

// 移除页面
stackedWidget->removeWidget(widget);

2.2 信号

cpp 复制代码
// 当前页面改变时发射
void currentChanged(int index);
void widgetRemoved(int index);

三、案例

QStackWidget核心

cpp 复制代码
 // 创建堆叠布局
    m_stackedWidget = new QStackedWidget(this);
    QWidget *gridPage = new QWidget();
 // 创建详情页
    m_detailpage = new detailpage(this);
    // 添加到堆叠窗口
    m_stackedWidget->addWidget(gridPage);
    m_stackedWidget->addWidget(m_detailpage);

这里我们可以看到两个页面都添加到堆叠布局中:

我们可以通过 m_stackedWidget->setCurrentIndex(index);的方式进行切换:

例如上面的那个当index=0时就是gridPage页面;当index=1时就是detailpage。

整体代码

mianwindow.h

cpp 复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include "detailpage.h"
#include <QMainWindow>
#include <QStackedWidget>
#include <QGridLayout>

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void onProductClicked(int index);
    void onBackFromDetail();

private:
    Ui::MainWindow *ui;

    struct ProductInfo
    {
        QString title;
        QString image;
        QString details;
    };

    void setupUI();
    void initProducts();
    bool eventFilter(QObject *obj, QEvent *event);

    QVector<ProductInfo> m_products;
    QStackedWidget *m_stackedWidget;
    QGridLayout *m_gridLayout;
    detailpage *m_detailpage;
};

#endif // MAINWINDOW_H

mainwindow.cpp

cpp 复制代码
#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QLabel>
#include <QMouseEvent>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setupUI();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::setupUI()
{
    resize(800, 600);

    // 创建堆叠布局
    m_stackedWidget = new QStackedWidget(this);

    QWidget *gridPage = new QWidget();
    m_gridLayout = new QGridLayout(gridPage);
    m_gridLayout->setSpacing(10);

    // 创建详情页
    m_detailpage = new detailpage(this);

    // 添加到堆叠窗口
    m_stackedWidget->addWidget(gridPage);
    m_stackedWidget->addWidget(m_detailpage);

    setCentralWidget(m_stackedWidget);

    // 初始化产品数据
    initProducts();

    // 创建产品卡片
    for (int i = 0; i < m_products.size(); ++i) {
        const ProductInfo &product = m_products[i];

        // 创建卡片容器
        QWidget *card = new QWidget();
        card->setFixedSize(200, 200);
        card->setProperty("productIndex", i);
        card->installEventFilter(this);

        // 卡片内部布局
        QVBoxLayout *cardLayout = new QVBoxLayout(card);

        // 产品图标
        QLabel *iconLabel = new QLabel(product.image);
        iconLabel->setAlignment(Qt::AlignCenter);
        cardLayout->addWidget(iconLabel);

        // 产品标题
        QLabel *titleLabel = new QLabel(product.title);
        titleLabel->setAlignment(Qt::AlignCenter);
        cardLayout->addWidget(titleLabel);

        // 添加到网格布局
        int row = i / 3;
        int col = i % 3;
        m_gridLayout->addWidget(card, row, col, Qt::AlignCenter);
    }

    // 连接信号
    connect(m_detailpage, &detailpage::backRequest, this, &MainWindow::onBackFromDetail);
}

void MainWindow::initProducts()
{
    m_products = {
        {
            "火灾预防",
            "🔥",
            "火灾预防是消防安全的第一道防线。本产品包含家庭用电安全规范、厨房用火注意事项等。"
        }
    };
}

void MainWindow::onProductClicked(int index)
{
    if (index >= 0 && index < m_products.size()) {
        const ProductInfo &product = m_products[index];
        m_detailpage->setProductInfo(product.title, product.image, product.details);
        m_stackedWidget->setCurrentIndex(1);
    }
}

void MainWindow::onBackFromDetail()
{
    m_stackedWidget->setCurrentIndex(0);
}

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
    if (event->type() == QEvent::MouseButtonPress) {
        QMouseEvent *mouseEvent = static_cast<QMouseEvent*>(event);
        if (mouseEvent->button() == Qt::LeftButton) {
            QWidget *card = qobject_cast<QWidget*>(obj);
            if (card) {
                int index = card->property("productIndex").toInt();
                onProductClicked(index);
                return true;
            }
        }
    }
    return QWidget::eventFilter(obj, event);
}

detailpage.h

cpp 复制代码
#ifndef DETAILPAGE_H
#define DETAILPAGE_H

#include <QWidget>
#include <QTextEdit>
#include <QPushButton>

class detailpage : public QWidget
{
    Q_OBJECT
public:
    explicit detailpage(QWidget *parent = nullptr);
    void setProductInfo(const QString &title, const QString &image, const QString &details);

signals:
    void backRequest();

private slots:
    void onBackClicked();

private:
    QTextEdit *m_detailsText;
    QPushButton *m_backButton;
};

#endif // DETAILPAGE_H

detailpage.cpp

cpp 复制代码
#include "detailpage.h"
#include <QVBoxLayout>
#include <QHBoxLayout>

detailpage::detailpage(QWidget *parent)
    : QWidget{parent}
{
    QVBoxLayout *mainLayout = new QVBoxLayout(this);

    // 返回按钮
    m_backButton = new QPushButton("返回");
    connect(m_backButton, &QPushButton::clicked, this, &detailpage::onBackClicked);

    // 详细信息显示
    m_detailsText = new QTextEdit();
    m_detailsText->setReadOnly(true);

    mainLayout->addWidget(m_backButton);
    mainLayout->addWidget(m_detailsText);
}

void detailpage::setProductInfo(const QString &title, const QString &image, const QString &details)
{
    QString formattedDetails = QString("<h2>%1</h2><p>%2</p>").arg(title, details);
    m_detailsText->setHtml(formattedDetails);
}

void detailpage::onBackClicked()
{
    emit backRequest();
}

四、效果

第一个界面

点击图标后跳转到第二个界面

相关推荐
TDengine (老段)1 分钟前
TDengine 常见问题 TOP7
大数据·数据库·时序数据库·常见问题·tdengine·涛思数据
+VX:Fegn08955 分钟前
计算机毕业设计|基于java+ vue共享单车信息系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
泡茶喝茶写代码12 分钟前
量化数据进阶:多维实战篇(第 11 篇):历史涨跌停价:涨跌停序列与止损线测算
java·python·股票数据api·股票数据·股票数据api接口·股票api数据接口·股票量化数据api
景熙552325 分钟前
单体项目编写思路和落地形式
java·开发语言
Ivanqhz26 分钟前
Slope One 算法详解:与矩阵分解、共现矩阵的异同
java·服务器·网络·人工智能·深度学习
mysqloffice36 分钟前
数智时代,核心系统数据库架构往哪走
数据库·人工智能
l1t43 分钟前
DeepSeek总结的 pgColumnar 1.0-alpha4 发布说明
数据库·postgresql
DBA_G1 小时前
南大通用GBase 8s数据库助力某农商行核心系统投产
数据库
Bs_MoneyMagnet1 小时前
基于springboot+vue的非遗物质文化遗产系统的设计与实现 源码+文档
java·vue.js·spring boot·后端·spring·毕业设计·计算机毕业设计
万物智能1 小时前
波形发生AD9833模块配置—【万物智能之开源鸿蒙OpenHarmony系统实战开发系列教程】
java