《QT实用小工具·四十五》可以在界面上游泳的小鱼

1、概述
源码放在文章末尾

该项目实现了灵动的小鱼,可以在界面上跟随鼠标点击自由的游泳,项目demo演示如下所示:
在这里插入图片描述

项目部分代码如下所示:

#include "magicfish.h"
#include <QtMath>
#include <QPainter>
#include <QPainterPath>
#include <QVariantAnimation>

MagicFish::MagicFish(QQuickPaintedItem *parent)
    : QQuickPaintedItem(parent),
      m_fishRadius(30),
      m_finLen(30 * 1.3),
      m_bodyHeight(30 * 3.2),
      m_headAlpha(200),
      m_bodyAlpha(225),
      M_finAlpha(120),
      m_mainAngle(0.0),
      m_curValue(0),
      m_wave(1.0),
      m_startFin(false),
      m_paintPoint(false)
{
    m_animation = new QVariantAnimation(this);
    m_animation->setDuration(180 * 1000);
    m_animation->setStartValue(0);
    m_animation->setEndValue(54000);
    m_animation->setLoopCount(-1);
    connect(m_animation, &QVariantAnimation::valueChanged, this, [this](const QVariant &value)
    {
        m_curValue = value.toInt();
        update();
    });

    connect(this, &QQuickItem::widthChanged, this, &MagicFish::resize);
    connect(this, &QQuickItem::heightChanged, this, &MagicFish::resize);

    m_animation->start();
}

void MagicFish::paint(QPainter *painter)
{
    painter->setRenderHint(QPainter::Antialiasing);
    QPointF middle_pos = QPointF(width() / 2, height() / 2);
    m_headPos = calcPoint(middle_pos, m_bodyHeight / 2.0, m_mainAngle);
    paintMyPoint(painter, m_headPos);
    paintMyPoint(painter, middle_pos);
    painter->setPen(Qt::NoPen);
    painter->setBrush(QBrush(QColor(20, 203, 232, 50)));
    painter->setBrush(QBrush(QColor(244, 92, 71, m_headAlpha)));
    painter->drawEllipse(m_headPos, m_fishRadius, m_fishRadius);

    qreal angle = m_mainAngle + qSin(qDegreesToRadians(m_curValue * 1.2 * m_wave)) * 2;
    QPointF end_pos = calcPoint(m_headPos, m_bodyHeight, angle - 180);
    QPointF pos1 = calcPoint(m_headPos, m_fishRadius, angle - 80);
    QPointF pos2 = calcPoint(end_pos, m_fishRadius * 0.7, angle - 90);
    QPointF pos3 = calcPoint(end_pos, m_fishRadius * 0.7, angle + 90);
    QPointF pos4 = calcPoint(m_headPos, m_fishRadius, angle + 80);

    QPointF central_left = calcPoint(m_headPos, m_bodyHeight * 0.56, angle - 130);
    QPointF central_right = calcPoint(m_headPos, m_bodyHeight * 0.56, angle + 130);
    QPainterPath path;
    path.moveTo(pos1);
    path.quadTo(central_left, pos2);
    path.lineTo(pos3);
    path.quadTo(central_right, pos4);
    path.lineTo(pos1);

    painter->setBrush(QBrush(QColor(244, 92, 71, m_bodyAlpha)));
    painter->drawPath(path);

    paintMyBody(painter, end_pos, m_fishRadius * 0.7, 0.6, angle);
    QPointF left_fin_pos = calcPoint(m_headPos, m_fishRadius * 0.9, angle + 110);
    paintMyFishFins(painter, left_fin_pos, true, angle);
    QPointF right_fin_pos = calcPoint(m_headPos, m_fishRadius * 0.9, angle - 110);
    paintMyFishFins(painter, right_fin_pos, false, angle);
}

void MagicFish::resize()
{
    m_fishRadius = qMin(width(), height()) / 10.0;
    m_finLen = m_fishRadius * 1.3;
    m_bodyHeight = m_fishRadius * 3.2;
}

QPointF MagicFish::calcPoint(const QPointF &pos, qreal length, qreal angle)
{
    qreal delta_x = qCos(qDegreesToRadians(angle)) * length;
    qreal delta_y = qSin(qDegreesToRadians(angle - 180)) * length;
    return QPointF(pos + QPointF(delta_x, delta_y));
}

void MagicFish::paintMyPoint(QPainter *painter, const QPointF pos)
{
    if(m_paintPoint)
    {
        painter->save();
        painter->setPen(QPen(Qt::black, 3));
        painter->setBrush(QBrush(Qt::black));
        painter->drawPoint(pos);
        painter->restore();
    }
}

void MagicFish::paintMyFishFins(QPainter *painter, const QPointF &pos, bool is_left, qreal father_angle)
{
    qreal contral_angle = 115;
    qreal fin_angle = m_startFin ? qSin(qDegreesToRadians(m_curValue * 16.1 * m_wave)) * 12.0 : 2;
    QPainterPath path;
    path.moveTo(pos);
    QPointF end_pos = calcPoint(pos, m_finLen, is_left ? father_angle + fin_angle + 180 :
                                                           father_angle - fin_angle - 180);
    QPointF control_pos = calcPoint(pos, m_finLen * 1.8, is_left ?
                                    father_angle + contral_angle + fin_angle :
                                    father_angle - contral_angle - fin_angle);

    path.quadTo(control_pos, end_pos);
    path.lineTo(pos);

    painter->save();
    painter->setBrush(QBrush(QColor(244, 92, 71, M_finAlpha)));
    painter->drawPath(path);
    painter->restore();
}

void MagicFish::paintMyBody(QPainter *painter, const QPointF &pos, qreal seg_r, qreal MP, qreal father_angle)
{
    qreal angle = father_angle + qCos(qDegreesToRadians(m_curValue * 1.5 * m_wave)) * 15;
    qreal length = seg_r * (MP + 1);
    QPointF end_pos = calcPoint(pos, length, angle - 180);

    QPointF pos1 = calcPoint(pos, seg_r, angle - 90);
    QPointF pos2 = calcPoint(end_pos, seg_r * MP, angle - 90);
    QPointF pos3 = calcPoint(end_pos, seg_r * MP, angle + 90);
    QPointF pos4 = calcPoint(pos, seg_r, angle + 90);

    painter->save();
    painter->setBrush(QBrush(QColor(244, 92, 71, m_headAlpha)));
    painter->drawEllipse(pos, seg_r, seg_r);
    painter->drawEllipse(end_pos, seg_r * MP, seg_r * MP);

    QPainterPath path;
    path.moveTo(pos1);
    path.lineTo(pos2);
    path.lineTo(pos3);
    path.lineTo(pos4);
    painter->drawPath(path);
    painter->restore();
    paintMyBody2(painter, end_pos, seg_r * 0.6, 0.4, angle);
}

void MagicFish::paintMyBody2(QPainter *painter, const QPointF &pos, qreal seg_r, qreal MP, qreal father_angle)
{
    qreal angle = father_angle + qSin(qDegreesToRadians(m_curValue * 1.5 * m_wave)) * 35;
    qreal length = seg_r * (MP + 2.7);
    QPointF end_pos = calcPoint(pos, length, angle - 180);

    QPointF pos1 = calcPoint(pos, seg_r, angle - 90);
    QPointF pos2 = calcPoint(end_pos, seg_r * MP, angle - 90);
    QPointF pos3 = calcPoint(end_pos, seg_r * MP, angle + 90);
    QPointF pos4 = calcPoint(pos, seg_r, angle + 90);
    paintMyTail(painter, pos, length, seg_r, angle);

    painter->save();
    painter->setBrush(QBrush(QColor(244, 92, 71, m_headAlpha)));
    painter->drawEllipse(end_pos, seg_r * MP, seg_r * MP);

    QPainterPath path;
    path.moveTo(pos1);
    path.lineTo(pos2);
    path.lineTo(pos3);
    path.lineTo(pos4);
    painter->drawPath(path);
    painter->restore();
}

void MagicFish::paintMyTail(QPainter *painter, const QPointF &pos, qreal length, qreal max_w, qreal angle)
{
    qreal w = qAbs(qSin(qDegreesToRadians(m_curValue * 1.7 * m_wave)) * max_w + m_fishRadius / 5.0 * 3.0);
    QPointF end_point1 = calcPoint(pos, length, angle - 180);
    QPointF end_point2 = calcPoint(pos, length - 10, angle - 180);

    QPointF pos1 = calcPoint(end_point1, w, angle - 90);
    QPointF pos2 = calcPoint(end_point1, w, angle + 90);
    QPointF pos3 = calcPoint(end_point2, w - m_fishRadius / 1.5, angle - 90);
    QPointF pos4 = calcPoint(end_point2, w - m_fishRadius / 1.5, angle + 90);

    QPainterPath path;
    path.moveTo(pos);
    path.lineTo(pos3);
    path.lineTo(pos4);
    path.lineTo(pos);
    painter->save();
    painter->setBrush(QBrush(QColor(244, 92, 71,     m_headAlpha)));
    painter->drawPath(path);

    path.closeSubpath();
    path.moveTo(pos);
    path.lineTo(pos1);
    path.lineTo(pos2);
    path.lineTo(pos);
    painter->drawPath(path);
    painter->restore();
}

void MagicFish::setWave(qreal value)
{
    m_wave = value;
}

qreal MagicFish::getFishR() const
{
    return m_fishRadius;
}

qreal MagicFish::getAngle()
{
    return m_mainAngle;
}

QRectF MagicFish::geometry() const
{
    return QRectF(x(), y(), width(), height());
}

QPointF MagicFish::getHeadPos() const
{
    return m_headPos;
}

void MagicFish::setCurrentAngle(qreal angle)
{
    m_mainAngle = angle;
    update();
}

void MagicFish::setFinAnimation(bool start)
{
    m_startFin = start;
}

void MagicFish::setFishR(int value)
{
    m_fishRadius = value;
    m_finLen = value * 1.3;
    m_bodyHeight = value * 3.2;
    update();
}

源码下载

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CentOS7安装和升级nginx

文章目录 一 环境准备二 安装nginx三 升级nginx四 注意事项 一 环境准备 公司等保要求修复nginx的应用漏洞&#xff0c;从1.12.2升级到1.20.2版本。 本机操作系统是CentOS7.9&#xff0c;主机IP是192.168.0.201&#xff0c;nginx是在服务器部署而非容器部署。 下列安装和升级…

Springboot + MySQL + html 实现文件的上传、存储、下载、删除

实现步骤及效果呈现如下&#xff1a; 1.创建数据库表&#xff1a; 表名&#xff1a;file_test 存储后的数据&#xff1a; 2.创建数据库表对应映射的实体类&#xff1a; import com.baomidou.mybatisplus.annotation.IdType;import com.baomidou.mybatisplus.annotation.Table…

《R语言与农业数据统计分析及建模》学习——回归分析

一、线性回归 线性回归是一种广泛用于数据分析、预测和建模的技术&#xff0c;可以帮助我们理解变量之间的关系&#xff0c;并进行预测和推断。 1、简单线性回归 简单线性回归是线性回归的一种特殊情况&#xff0c;适用于只有一个自变量和一个因变量的情况。 在R语言中&#x…

QT c++ 代码布局原则 简单例子

本文描述QT c widget代码布局遵循的原则&#xff1a;实中套虚&#xff0c;虚中套实。 本文最后列出了代码下载链接。 在QT6.2.4 msvc2019编译通过。 所谓实是实体组件&#xff1a;比如界面框、文本标签、组合框、文本框、按钮、表格、图片框等。 所谓虚是Layout组件&#x…

IT廉连看——UniApp——样式绑定

IT廉连看——UniApp——样式绑定 一、样式绑定 两种添加样式的方法&#xff1a; 1、第一种写法 写一个class属性&#xff0c;然后将css样式写在style中。 2、第二种写法 直接把style写在class后面 添加一些效果&#xff1a;字体大小 查看效果 证明这样添加样式是没有问题的…

WPF —— MVVM 指令执行不同的任务实例

标签页 设置两个按钮&#xff0c; <Button Content"修改状态" Width"100" Height"40" Background"red"Click"Button_Click"></Button><Button Content"测试"Width"100"Height"40&…

clickhous学习之旅二

接上回继续鼓捣clickhouse 1.常用数据类型 1.1整型 固定长度的整型&#xff0c;包括有符号整型或无符号整型。整型范围(-2n-1~2n-1-1): Int8 - [-128 :127] -->相当于java中的byte Int16-[-32768 :32767] -->相当于java中的short Int32-[-2147483648 :2147483647] -…

最新官方破解版会声会影2024永久序列号和激活码

会声会影2024是一款功能强大的视频编辑软件&#xff0c;它集合了视频剪辑、音频调整、特效添加等多项功能于一身&#xff0c;为用户提供了一个全面且易用的视频制作平台。无论是初学者还是专业视频编辑人员&#xff0c;都能在这款软件中找到满足自己创作需求的工具。 会声会影最…

基于残差神经网络的汉字识别系统+pyqt前段界面设计

研究内容: 中文汉字识别是一项具有挑战性的任务&#xff0c;涉及到对中文字符的准确分类。在这个项目中&#xff0c;目标是构建一个能够准确识别中文汉字的系统。这个任务涉及到数据集的收集、预处理、模型训练和评估等步骤。尝试了使用残差神经网络&#xff08;ResNet&#x…

windows电脑改造为linux

有个大学用的旧笔记本电脑没啥用了&#xff0c;决定把它改成linux搭一个服务器&#xff1b; 一、linux安装盘制作 首先要有一个大于8G的U盘&#xff0c;然后去下载需要的linux系统镜像&#xff0c;我下的是ubuntu&#xff0c;这里自选版本 https://cn.ubuntu.com/download/d…

中国移动旋转验证码的识别过程

一、前言 今天有空研究了一下这个移动的登录&#xff0c;发现获取手机验证码的时候会弹出一种旋转验证码。这种验证码确实挺头疼。所以顺便研究了一下如何识别。 验证码的样子大家先看一下。看看大家有没有什么更好是思路。 二、验证码识别 我这里就直接上代码。我这里是使用…

SpringMVC基础篇(四)

文章目录 1.视图1.基本介绍1.视图介绍2.为什么需要自定义视图 2.自定义视图实例1.思路分析2.代码实例1.view.jsp2.接口3.配置自定义视图解析器springDispatcherServlet-servlet.xml4.自定义视图MyView.java5.view_result.jsp6.结果展示 3.自定义视图执行流程4.自定义视图执行流…

web安全---xss漏洞/beef-xss基本使用

what xss漏洞----跨站脚本攻击&#xff08;Cross Site Scripting&#xff09;&#xff0c;攻击者在网页中注入恶意脚本代码&#xff0c;使受害者在浏览器中运行该脚本&#xff0c;从而达到攻击目的。 分类 反射型---最常见&#xff0c;最广泛 用户将带有恶意代码的url打开&a…

E-MapReduce极客挑战赛季军方案

前一段时间我参加了E-MapReduce极客挑战赛&#xff0c;很幸运的获得了季军。在这把我的比赛攻略给大家分享一下&#xff0c;希望可以抛砖引玉。 赛题分析与理解 赛题背景&#xff1a; 大数据时代&#xff0c;上云已成为越来越多终端客户大数据方案的落地选择&#xff0c;阿里…

Phi-3-mini-4k-instruct 的功能测试

Model card 介绍 Phi-3-Mini-4K-Instruct 是一个 3.8B 参数、轻量级、最先进的开放模型&#xff0c;使用 Phi-3 数据集进行训练&#xff0c;其中包括合成数据和经过过滤的公开可用网站数据&#xff0c;重点是 高品质和推理密集的属性。 该型号属于 Phi-3 系列&#xff0c;Mini…

Golang | Leetcode Golang题解之第58题最后一个单词的长度

题目&#xff1a; 题解&#xff1a; func lengthOfLastWord(s string) (ans int) {index : len(s) - 1for s[index] {index--}for index > 0 && s[index] ! {ansindex--}return }

虚拟机扩容-根目录挂载sda1的空间不足

提醒&#xff01;不管成不成功&#xff0c;一定要先备份一份虚拟机&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 走过路过点个关注吧&#xff0c;想到500粉丝&#xff0c;哭。一、查看分区情况 df -h可以看到/dev/sda1已经被占满了 2.关闭虚拟机&#xff…

windows驱动开发-WDF对象

WDF封装了大量的WDF对象&#xff0c;不过&#xff0c;和应用层不一样&#xff0c;不用去尝试从WDF框架对象类上派生和改写原有的WDF类&#xff0c;本意WDF就是希望我们使用这些对象和类&#xff0c;而不是创造新的奇怪的类。 每个WDF对象都代表着对一项驱动需要使用的子功能的…

vue学习的预备知识为学好vue打好基础

目录 Vue是什么 &#xff1f;如何使用Vue &#xff1f;Vue ApiVue入口apiVue实例apiVue函数api 无构建过程的渐进式增强静态HTMLVue模块化构建工具npmyarnWebpackvue-cliVite Vue是什么 &#xff1f; 文章基于Vue3叙述。 Vue (发音为 /vjuː/&#xff0c;类似 view) 是一款用于…

179. 最大数(LeetCode)

文章目录 前言一、题目讲解二、算法原理三、代码编写1.仿函数写法2.lambda表达式 四、验证五.总结 前言 在本篇文章中&#xff0c;我们将会带着大家采用贪心的方法解决LeetCode中最大数这道问题&#xff01;&#xff01;&#xff01; 一、题目讲解 一组非负整数&#xff0c;包…
最新文章