遮挡式引导界面设计

语言方向: 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;
};
相关推荐
xcyxiner2 天前
DicomViewer (dcmtk读取dcm文件)5
qt
xcyxiner2 天前
DicomViewer (后台线程处理文件)4
qt
xcyxiner3 天前
DicomViewer (添加模型类)3
qt
xcyxiner4 天前
DicomViewer (目录调整) 2
qt
xcyxiner4 天前
dcmtk vtk vtk-dicom(gdcm) 编译(debug) v2
qt
桥田智能6 天前
桥田智能 QT-650S:面向白车身焊装的 800kg 重载快换解决方案
开发语言·qt·系统架构
森G6 天前
75、服务器源码解析---------云视频服务项目
linux·服务器·网络·c++·qt
森G6 天前
77、线程池原理和实现------服务器源码解析----云视频服务项目
服务器·c++·qt
森G6 天前
71、打包发布---------打包发布
c++·qt
初圣魔门首席弟子6 天前
Node.js 详细介绍(知识库版)
windows·qt·node.js·知识库