遮挡式引导界面设计

语言方向: QT C++

在你的 PTP 界面调用

cpp 复制代码
// 在你的 PTP 窗口类中添加
#include "PtpGuide.h"
PtpGuide *m_guide;

// 初始化时调用
m_guide = new PtpGuide(this);

// 添加你的按钮步骤(改成你界面的按钮名)
m_guide->addStep(ui->btn_home,    "① 请点击【回零】按钮");
m_guide->addStep(ui->btn_enable,  "② 请点击【伺服使能】");
m_guide->addStep(ui->btn_set_pos, "③ 请设置目标位置");
m_guide->addStep(ui->btn_start,   "④ 点击【启动】执行PTP运动");

// 开始按钮
void PtpWindow::on_btn_startGuide_clicked()
{
    m_guide->start();
}

PtpGuide.h

cpp 复制代码
#include <QObject>
#include <QPushButton>
#include <QMessageBox>
#include <QTimer>
#include <QLabel>
#include "MaskWidget.h"

// 步骤结构体
struct GuideStep
{
    QPushButton *targetBtn;
    QString tipMsg;
};

class PtpGuide : public QObject
{
    Q_OBJECT
public:
    explicit PtpGuide(QWidget *parentPage);
    void addStep(QPushButton *btn, const QString &msg);
    void start();
    void stop();

private slots:
    void nextStep();
    void onBtnClicked();

private:
    void showCurrentStep();
    void clearHighlight();
    void showTipBalloon();

    QWidget *m_parentPage;
    MaskWidget *m_mask;       // 半透明遮罩
    QLabel *m_tipLabel;       // 固定提示框
    QList<GuideStep> m_steps;
    int m_currentStep = -1;
    QPushButton *m_lastBtn = nullptr;
};

ptpguide.cpp

cpp 复制代码
#include "PtpGuide.h"

PtpGuide::PtpGuide(QWidget *parentPage)
    : QObject(parentPage), m_parentPage(parentPage)
{
    // 创建遮罩
    m_mask = new MaskWidget(m_parentPage);
    m_mask->setGeometry(m_parentPage->rect());
    m_mask->hide();

    // 创建提示框
    m_tipLabel = new QLabel(m_parentPage);
    m_tipLabel->setStyleSheet("background: white; color: black; padding:6px; border:1px solid gray;");
    m_tipLabel->setVisible(false);
}

// 添加步骤
void PtpGuide::addStep(QPushButton *btn, const QString &msg) {
    m_steps.append({btn, msg});
}

// 开始引导
void PtpGuide::start() {
    if (m_steps.isEmpty()) return;
    m_currentStep = 0;
    m_mask->show();
    m_mask->raise();
    showCurrentStep();
}

// 显示当前步骤:遮罩挖空 + 高亮 + 提示
void PtpGuide::showCurrentStep() {
    auto step = m_steps[m_currentStep];
    clearHighlight();

    m_lastBtn = step.targetBtn;
    m_mask->setTargetButton(m_lastBtn);

    // 按钮高亮
    m_lastBtn->setStyleSheet("border:3px solid #ff5500; background:#fff9c4;");

    // 提示框显示在按钮上方
    showTipBalloon();

    // 点击按钮 → 下一步
    connect(m_lastBtn, &QPushButton::clicked, this, &PtpGuide::onBtnClicked, Qt::UniqueConnection);
}

// 提示框
void PtpGuide::showTipBalloon() {
    auto step = m_steps[m_currentStep];
    QPoint pos = step.targetBtn->mapToParent(QPoint(0, -40));
    m_tipLabel->setText(step.tipMsg);
    m_tipLabel->move(pos);
    m_tipLabel->show();
    m_tipLabel->raise();
}

// 清除高亮
void PtpGuide::clearHighlight() {
    if (m_lastBtn) {
        m_lastBtn->setStyleSheet("");
        disconnect(m_lastBtn, nullptr, this, nullptr);
    }
}

// 按钮点击 → 延迟进入下一步
void PtpGuide::onBtnClicked() {
    QTimer::singleShot(300, this, &PtpGuide::nextStep);
}

// 下一步
void PtpGuide::nextStep() {
    m_currentStep++;
    if (m_currentStep >= m_steps.size()) {
        stop();
        QMessageBox::information(m_parentPage, "完成", "PTP操作引导已完成!");
        return;
    }
    showCurrentStep();
}

// 停止引导
void PtpGuide::stop() {
    clearHighlight();
    m_mask->hide();
    m_tipLabel->hide();
}

MaskWidget.hpp

cpp 复制代码
#include <QWidget>
#include <QPainter>
#include <QPaintEvent>

class MaskWidget : public QWidget
{
    Q_OBJECT
public:
    explicit MaskWidget(QWidget *parent = nullptr) : QWidget(parent) {
        setAttribute(Qt::WA_TransparentForMouseEvents); // 遮罩不拦截鼠标
    }

    // 设置要高亮显示的按钮
    void setTargetButton(QWidget *btn) {
        m_targetBtn = btn;
        update();
    }

protected:
    void paintEvent(QPaintEvent *event) override {
        if (!m_targetBtn) return;

        QPainter p(this);
        p.fillRect(rect(), QColor(0, 0, 0, 180)); // 半透明黑遮罩

        // 挖空:按钮区域变透明
        QRect btnRect = m_targetBtn->rect();
        QPoint globalPos = m_targetBtn->mapToGlobal(pos());
        QRect targetRect = QRect(globalPos, btnRect.size());

        p.setCompositionMode(QPainter::CompositionMode_Clear);
        p.fillRect(targetRect, Qt::transparent);
    }

private:
    QWidget *m_targetBtn = nullptr;
};
相关推荐
酬勤-人间道1 小时前
VTK 与 Cesium-native 结合实践:小场景三维编辑 + 数字地球精准贴合
c++·qt·vtk·遥感·岩土·cesium-native
誰能久伴不乏2 小时前
Qt C++ 解析 JSON 完全指南:从核心概念到工业级实战
c++·qt·json
雪的季节3 小时前
Qt 高性能绘图的核心原理
qt
Irissgwe3 小时前
一、Qt 概述
c++·qt·gui·qt creator
m0_617493943 小时前
PySide6/PyQt6实现中英文切换完整教程(Qt Designer + Qt Linguist + 动态切换)
开发语言·qt
咸鱼翻身小阿橙3 小时前
文件读写 + Qt Model/View + 自定义分页+搜索过滤
java·数据库·qt
郝学胜-神的一滴3 小时前
Qt 高级开发 021:零基础吃透 QVBoxLayout 垂直布局
开发语言·c++·qt·程序人生·用户界面
Irissgwe4 小时前
二、信号与槽
c++·qt·信号与槽
Dovis(誓平步青云)6 小时前
《QT学习第四篇:常见事件与UDP、TCP、文件系统、(锁、信号量、条件变量》
c语言·开发语言·汇编·qt