Qt实现引导界面UITour

介绍

最近做了一款键鼠自动化,想第一次安装打开后搞一个引导界面,找了好多资料没啥参考,偶然发现qt有引导界面如下图。

Qt整挺好,但是未找到源码,真的不想手撸,无奈实在找不到,下图是仿照qt实现。

废话少说

直接上代码

cpp 复制代码
#ifndef TOURGUIDE_H
#define TOURGUIDE_H

#include <QWidget>
#include <QPaintEvent>
#include <QPainter>
#include <QPalette>
#include <QBrush>


enum WSAD_POS {
    TOP_POS,
    DOWN_PPOS,
    LEFT_POS,
    RIGHT_POS
};
class TourGuide : public QWidget
{
    Q_OBJECT
public:
    explicit TourGuide(QWidget* w, QWidget *parent = 0);

    void onAddWidget(QWidget* w, QString title, QStringList contentList, int pos);
signals:

public slots:

protected:
    void paintEvent(QPaintEvent *event);
    void mousePressEvent(QMouseEvent *event);
private:
    //绘制箭头 WSAD绘制方向
    void drawArrows(QPainter& painter, QPoint pos, QRect rect, WSAD_POS WSAD);
private:
    QList<QWidget*> m_ListWidget;
    QList<QString> m_ListWidgetStr;
    QList<QStringList> m_ListWidgetStrList;
    QList<WSAD_POS> m_ListWidgetPos;

    int m_index = 0;

    QWidget* m_MainWindows;
    QLine targetLine;
};

#endif // TOURGUIDE_H
cpp 复制代码
#include "tourguide.h"

#include <QDebug>
TourGuide::TourGuide(QWidget *w, QWidget *parent) : QWidget(parent)
{
    m_MainWindows = w;
}

void TourGuide::onAddWidget(QWidget *w, QString title, QStringList contentList, int pos)
{
    m_ListWidget << w;
    m_ListWidgetStr << title;
    m_ListWidgetStrList << contentList;

    m_ListWidgetPos << WSAD_POS(pos);
}

void TourGuide::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    if (m_index < 0 || m_index >= m_ListWidget.size())
        return;

    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);

    QWidget *currentWidget = m_ListWidget[m_index];
    if (!currentWidget)
        return;


    // 获取QWidget在主窗体的位置
    QPoint guidePos = currentWidget->mapTo(m_MainWindows, QPoint(0, 0));
    QRect rect(guidePos.x(), guidePos.y(), currentWidget->width(), currentWidget->height());
    //循环如果包含该ui就不绘制
    painter.setPen(Qt::NoPen);
    painter.setBrush(QColor(0, 0, 0, 100));

    // 当前widget的大小
    int fullWidth = this->width();
    int fullHeight = this->height();

    // 计算四周矩形区域
    QRect topRect(0, 0, fullWidth, rect.y());
    QRect bottomRect(0, rect.y() + rect.height(), fullWidth, fullHeight - (rect.y() + rect.height()));
    QRect leftRect(0, rect.y(), rect.x(), rect.height());
    QRect rightRect(rect.x() + rect.width(), rect.y(), fullWidth - (rect.x() + rect.width()), rect.height());

    // 设置笔刷
    painter.setBrush(QColor(0, 0, 0, 100));

    // 绘制四周矩形 把ui的位置进行空出来,绘制它的四个区域,仅支持规则ui,这样就不支持奇形怪状
    painter.drawRect(topRect);
    painter.drawRect(bottomRect);
    painter.drawRect(leftRect);
    painter.drawRect(rightRect);

    painter.setBrush(QColor(0, 0, 0, 0));

    QPen pen(Qt::green);

    //圈出来
    pen.setWidth(1);
    painter.setPen(pen);
    painter.drawRect(rect);

    drawArrows(painter, guidePos, currentWidget->rect(), m_ListWidgetPos.at(m_index));

    // 绘制矩形框和箭头
    // 绘制文字
    painter.setPen(Qt::white); // 设置文字颜色为白色
    QFont font = painter.font(); // 获取当前字体设置
    font.setPointSize(18); // 设置字体大小
    font.setBold(true); // 设置为粗体
    painter.setFont(font); // 应用设置后的字体
    // 获取文本的宽度和高度
    QRectF textRect = painter.boundingRect(QRectF(), Qt::AlignCenter, m_ListWidgetStr.at(m_index));

    // 计算文字应该绘制的位置,使其居中在窗口中央
    qreal x = (this->width() - textRect.width()) / 2;
    qreal y = (this->height() - textRect.height()) / 2;
    // 绘制标题文字
    painter.drawText(QPointF(x, y), m_ListWidgetStr.at(m_index));
    QStringList list = m_ListWidgetStrList.at(m_index);


    // 绘制子文字
    for (int i = 0 ; i < list.size(); ++i) {
        textRect = painter.boundingRect(QRectF(), Qt::AlignCenter, list.at(i));
        x = (this->width() - textRect.width()) / 2;
        y = (this->height() - textRect.height()) / 2 + ((i+1) * 40);
        font.setPointSize(12);
        font.setBold(false);
        painter.setFont(font); // 应用设置后的字体
        // 绘制标题文字
        painter.drawText(QPointF(x, y), list.at(i));
    }
}

void TourGuide::mousePressEvent(QMouseEvent *event)
{
    if (event->type() == QMouseEvent::MouseButtonPress) {
        this->update();
        qDebug() << m_index;
        if (m_index < m_ListWidget.size()) {
            m_index++;
        }
        else {
            this->close();
        }
    }
}

void TourGuide::drawArrows(QPainter &painter, QPoint pos, QRect rect, WSAD_POS WSAD)
{
    QPoint f1Start;
    QPoint f1Stop;
    QPoint f2Start;
    QPoint f2Stop;
    QPoint f3Start;
    QPoint f3Stop;
    if (WSAD == TOP_POS) {
        // 绘制箭头
        f1Start = QPoint(pos.x() + (rect.width() / 2), pos.y() - 5);
        f1Stop = QPoint(pos.x() + (rect.width() / 2) - 6, pos.y() - 12);
        //绘制两边的线
        f2Start = QPoint(pos.x() + (rect.width() / 2), pos.y() - 5);
        f2Stop = QPoint(pos.x() + (rect.width() / 2) + 6, pos.y() - 12);

        //绘制中间的线
        f3Start = QPoint(pos.x() + (rect.width() / 2), pos.y() - 5);
        f3Stop = QPoint(pos.x() + (rect.width() / 2), pos.y() - 20);
    }
    else if (WSAD == DOWN_PPOS) {
        // 绘制箭头
        f1Start = QPoint(pos.x() + (rect.width() / 2), pos.y() + rect.height() + 5);
        f1Stop = QPoint(pos.x() + (rect.width() / 2) - 6, pos.y() + rect.height() + 12);
        //绘制两边的线
        f2Start = QPoint(pos.x() + (rect.width() / 2), pos.y() + rect.height() + 5);
        f2Stop = QPoint(pos.x() + (rect.width() / 2) + 6, pos.y() + rect.height() + 12);

        //绘制中间的线
        f3Start = QPoint(pos.x() + (rect.width() / 2), pos.y() + rect.height() + 5);
        f3Stop = QPoint(pos.x() + (rect.width() / 2), pos.y() + rect.height() + 20);
    }
    else if (WSAD == LEFT_POS) {
        // 绘制箭头
        f1Start = QPoint(pos.x() - 5, pos.y() + (rect.height() / 2));
        f1Stop = QPoint(pos.x() - 12, pos.y() + 5);
        //绘制两边的线
        f2Start = QPoint(pos.x() - 5, pos.y() + (rect.height() / 2));
        f2Stop = QPoint(pos.x() - 12, pos.y() + (rect.height() / 2) + 6);

        //绘制中间的线
        f3Start = QPoint(pos.x() - 5, pos.y() + rect.height() / 2);
        f3Stop = QPoint(pos.x() - 20, pos.y() + rect.height() / 2);
    }
    else if (WSAD == RIGHT_POS) {
        // 绘制箭头
        f1Start = QPoint(pos.x() + rect.width() + 5, pos.y() + (rect.height() / 2));
        f1Stop = QPoint(pos.x() + rect.width() + 12, pos.y() + 5);
        //绘制两边的线
        f2Start = QPoint(pos.x() + rect.width() + 5, pos.y() + (rect.height() / 2));
        f2Stop = QPoint(pos.x() + rect.width() + 12, pos.y() + (rect.height() / 2) + 6);

        //绘制中间的线
        f3Start = QPoint(pos.x() + rect.width() + 5, pos.y() + rect.height() / 2);
        f3Stop = QPoint(pos.x() + rect.width() + 20, pos.y() + rect.height() / 2);
    }

    QPen pen(Qt::green);
    pen.setWidth(2);
    painter.setPen(pen);
    painter.drawLine(f1Start, f1Stop);
    painter.drawLine(f2Start, f2Stop);
    painter.drawLine(f3Start, f3Stop);
}

调用方式

cpp 复制代码
    m_T = new TourGuide(this, this);
    m_T->onAddWidget(ui->pushButton, "这是第1个按钮", QStringList() << "他是第1个", 0);
    m_T->onAddWidget(ui->pushButton_2, "这是第2个按钮", QStringList() << "他是第2个", 1);
    m_T->onAddWidget(ui->pushButton_3, "这是第3个按钮", QStringList() << "他是第3个", 2);
    m_T->onAddWidget(ui->pushButton_4, "这是第4个按钮", QStringList() << "他是第4个", 3);
    m_T->setFixedSize(this->size());

1.优化半透明色绘制,由于前期采用双for循环绘制,导致刷新效率降低,现采用计算四周区域进行绘制,但是这样会带来仅支持规则区域,正方形,长方形,如果是不规则ui还得用for循环来判断,如果想实现那就要再写个算法来优化,例如如果是圆形那就计算出它的四边区域位置然后将他空出一个正方形然后进行for循环修补。

相关推荐
WooaiJava6 小时前
流式TTS音频播放项目 - 面试问答(后端)
java·开发语言
新缸中之脑6 小时前
开发AI代理必备的8个Python 库
开发语言·人工智能·python
暴走十八步6 小时前
PHP+vscode开启调试debug
开发语言·vscode·php
郝学胜-神的一滴6 小时前
Python 列表 vs 数组:深入解析与最佳选择指南
开发语言·python·程序人生
杜子不疼.6 小时前
基于ATVC模板库的Ascend C Vector算子快速开发指南
c语言·开发语言·mfc
MSTcheng.6 小时前
【C++】C++11新特性(三)
开发语言·c++·c++11
learning-striving6 小时前
kali连不上网解决方法
linux·开发语言·网络·php·kali
田野追逐星光6 小时前
STL容器list的模拟实现
开发语言·c++·list
摇滚侠6 小时前
macbook shell 客户端推荐 Electerm macbook 版本下载链接
java·开发语言
程序员布吉岛6 小时前
Java 后端定时任务怎么选:@Scheduled、Quartz 还是 XXL-Job?(对比 + 避坑 + 选型)
java·开发语言