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();
}

四、效果

第一个界面

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

相关推荐
洲星河ZXH1 小时前
Java,比较器
java·开发语言·算法
l***37091 小时前
spring 跨域CORS Filter
java·后端·spring
CoderYanger1 小时前
递归、搜索与回溯-FloodFill:33.太平洋大西洋水流问题
java·算法·leetcode·1024程序员节
P***84391 小时前
idea创建springBoot的五种方式
java·spring boot·intellij-idea
yuanhello1 小时前
【Android】Android的键值对存储方案对比
android·java·android studio
F***E2391 小时前
SQL中的REGEXP正则表达式使用指南
数据库·sql·正则表达式
2501_941142931 小时前
云原生微服务环境下服务熔断与降级优化实践——提升系统稳定性与容错能力
java·大数据·网络
2501_941404311 小时前
多云环境下微服务化AI大模型的企业部署与优化实践指南
java
张较瘦_1 小时前
数据库 | 从宠物管理系统看懂数据库多表关联查询:把零散的数据“串”起来
数据库·oracle·宠物