Qt实现引导界面UITour

news2024/11/16 2:55:27

介绍

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

在这里插入图片描述

Qt整挺好,但是未找到源码,真的不想手撸,无奈实在找不到,下图是仿照qt实现。
在这里插入图片描述
废话少说

直接上代码

#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

#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就不绘制
    for (int i = 0 ; i < this->width(); ++i) {
        for (int j = 0 ; j < this->height(); ++j) {
            if (!rect.contains(QPoint(i, j))) {
                painter.setPen(Qt::NoPen);
                painter.setBrush(QColor(0, 0, 0, 100));
                painter.drawRect(i, j, 1, 1);
            }
        }
    }

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

调用方式

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/818166.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

在Vue中使用深度选择器定制Element Plus组件样式

介绍&#xff1a; 在Vue.js开发中&#xff0c;我们经常使用Element Plus作为UI组件库&#xff0c;它提供了丰富的组件供我们使用。然而&#xff0c;有时候我们希望对Element Plus的组件样式进行一些定制&#xff0c;比如调整字体大小、改变颜色等。在这篇博客中&#xff0c;我…

【GitOps系列】如何实施金丝雀发布?

文章目录 前言金丝雀发布概述金丝雀实战创建生产环境 部署金丝雀环境配置金丝雀策略金丝雀发布自动化创建 Rollout 对象创建 Service 和 Ingress 对象访问生产环境金丝雀发布自动化 访问 Argo Rollout Dashboard自动化原理结语 前言 蓝绿发布是一种通过资源冗余来换取回滚效率的…

关于jar文件反编译

最近在搞tck测试&#xff0c;想要将其日志转换成apdu脚本&#xff0c;结果出现默认输出最大长度不足&#xff0c;输出被省略现象。 软件log出现的错误信息 ... Output overflow: JavaTest Harness has limited the test output to the text to that at the beginning and the…

stable-diffusion-webui 启动服务,卡在浏览器loading中, 重定向解决

最新的code&#xff0c;按步骤安装&#xff0c;趟完pip和github的坑&#xff0c;终于启动服务 然后悲催的卡在浏览器这一步&#xff0c;一直在loading&#xff0c;折腾一下午&#xff0c;尝试可能有效的步骤&#xff0c;也许最后一步才有用&#xff1a; 1. 启动IIS服务 2. 配…

Java课题笔记~Maven基础

2、Maven 基础 2.1 Maven安装与配置 下载安装 配置&#xff1a;修改安装目录/conf/settings.xml 本地仓库&#xff1a;存放的是下载的jar包 中央仓库&#xff1a;要从哪个网站去下载jar包 - 阿里云的仓库 2.2 创建Maven项目

爬虫006_python中的运算符_算术运算符_赋值运算符_复合赋值运算符_比较运算符_逻辑运算符_逻辑运算符性能提升---python工作笔记024

首先看加减乘除 然后看这里的 // 是取整数部分,不是四舍五入 然后%这个是取余数 然后**是,几次方那种 指数

游游的排列构造

示例1 输入 5 2 输出 3 1 5 2 4 示例2 输入 5 3 输出 2 1 4 3 5 #include<bits/stdc.h> using namespace std; typedef long long ll; const int N1e55; int n,k; int main(){scanf("%d%d",&n,&k);int xn-k1;int yn-k;int f1;for(int i1;i&l…

八大排序算法--希尔排序(动图理解)

目录 希尔排序 概念 算法思路 动画演示 代码如下 复杂度分析 时间复杂度测试 运行结果 完整代码 创作不易&#xff0c;如果本篇博客对您有一定的帮助&#xff0c;大家记得留言点赞哦。 希尔排序 概念 希尔排序是插入排序的一种&#xff0c;是对直接插入排序的优化。其…

Docker基础命令(一)

Docker使用1 一、运行终端 打开终端&#xff0c;输入docker images &#xff0c;如果运行正常&#xff0c;表示docker已经可以在本电脑上使用了 二、docker常用命令 指令说明docker images查看已下载的镜像docker rmi 镜像名称:标签名删除已下载的镜像docker search 镜像从官…

Python3.9.17配置openssl

下载python3.9.17和openssl3.1.1的安装包 wget https://www.python.org/ftp/python/3.9.17/Python-3.11.4.tgz wget https://www.openssl.org/source/openssl-3.1.1.tar.gz# 解压 tar -xzf openssl-3.1.1.tar.gz tar -xzf Python-3.9.17.tgz 1、安装openssl cd openssl-3.1.…

手机/平板电脑作为pc电脑扩展屏——Splashtop Wired XDisplay使用教程

Splashtop Wired XDisplay使用教程 写在前面这个软件能做什么软件安装开始使用如何拓展屏幕Wired XDisplay 找不到第二个屏幕或点击扩展没反应怎么办&#xff1f;Wired XDisplay扩展屏黑屏怎么办 写在前面 一直想买一个扩展屏&#xff0c;但实际需求使用的次数并不是很多。所以…

js全端支持的深拷贝structuredClone

Jul 7, 2023 经过一年半的试用&#xff0c;structuredClone转正了&#xff0c;全端可以正式使用。 https://developer.mozilla.org/en-US/docs/Web/API/structuredClone

ansible安装lnmp(集中式)

文章目录 一、安装nginx二、安装mysql三、安装php测试&#xff1a; 一、安装nginx - name: the nginx playhosts: webserversremote_user: roottasks:- name: stop firewalld #关闭防火墙service: namefirewalld statestopped enabledno- name: selinux stopc…

2023-07-31:用r、e、d三种字符,拼出一个回文子串数量等于x的字符串。 1 <= x <= 10^5。 来自百度。

2023-07-31&#xff1a;用r、e、d三种字符&#xff0c;拼出一个回文子串数量等于x的字符串。 1 < x < 10^5。 来自百度。 答案2023-07-31&#xff1a; 大体步骤如下&#xff1a; 1.初始化一个字符串builder&#xff0c;用于构建结果字符串。 2.初始化一个字符变量c…

【SpringBoot】| SpringBoot 和 web组件

目录 一&#xff1a;SpringBoot 和 web组件 1. SpringBoot中使用拦截器&#xff08;重点&#xff09; 2. SpringBoot中使用Servlet 3. SpringBoot中使用过滤器&#xff08;重点&#xff09; 4. 字符集过滤器的应用 一&#xff1a;SpringBoot 和 web组件 1. SpringBoot中使…

yellowbrick:一款特征工程可视化神器!

在建立模型之前一个非常重要的工作就是做特征工程&#xff0c;而在特征工程的过程中&#xff0c;探索性数据分析又是必不可少的一部分。 本次介绍一款功能十分强大的特征工程可视化工具&#xff1a;yellowbrick&#xff0c;包括雷达、一维排序、PCA、特征重要性、递归消除、正…

vue2实现一个树型控件(支持展开树与checkbox勾选)

目录 vue2实现一个树型控件(支持展开树与checkbox勾选)TreeItem.vueTree.vue效果 vue2实现一个树型控件(支持展开树与checkbox勾选) TreeItem.vue <template><div class"tree-item"><span click"toggleExpanded" class"icon" v…

用户需求转化为产品需求的5大注意事项

用户需求不等于产品需求&#xff0c;如果将用户需求和产品需求混为一谈&#xff0c;往往容易产生需求不完整、需求错误以及后期需求变更频繁等问题&#xff0c;那么用户需求转化为产品需求有什么注意事项&#xff1f; 1、了解需求转化落地逻辑流程 需要注意&#xff0c;用户需求…

DT水下照明学习

ocean1.timetime*.5; 水草动画 整体样子 叶子数量相关设置 植物运动相关 晃动不明显 增加这里的值 螺旋 弯曲播放&#xff0c;植物不会变直 表达式 kelp1.spiralMinsin(frame*.1)/5; 水泡 particleShape1.spriteScaleXPP particleShape1.spriteScaleYPP rand(0.1,0.5); part…

Nginx 【实战篇】 ---- Nginx 实战(购买服务器、域名、申请证书)

Nginx 【实战篇】 ---- Nginx 实战 1. 购买域名2. 购买服务器3. 服务器的基础配置和ssh连接4. 配置 LNMP 环境和防火墙配置4.1 配置 LNMP 环境4.2 修改防火墙配置 5. 将域名解析到服务器上6. 在线申请证书7. 将刚申请的证书配置到Nginx上 1. 购买域名 2. 购买服务器 域名和服务…