Qt桌面应用开发 第八天(综合项目一 飞翔的鸟)

news2024/11/28 13:46:30

目录

1.鸟类创建

2.鸟动画实现

3.鼠标拖拽

4.自动移动

5.右键菜单

6.窗口透明化


项目需求:

实现思路:

  1. 创建项目
  2. 导入资源
  3. 鸟类创建
  4. 鸟动画实现
  5. 鼠标拖拽实现
  6. 自动移动
  7. 右键菜单
  8. 窗口透明化

1.鸟类创建

①鸟类中包含鸟图片、鸟图片的最小值下标和最大值下标

class Bird : public QWidget
{
    Q_OBJECT
public:
    explicit Bird(QWidget *parent = nullptr);

    QPixmap m_Bird_Pix;//鸟显示的图片

    int min=1;//最小值图片下标
    int max=2;//最大值图片下标

signals:

public slots:
};

②将鸟的图片资源加载到对应项目下的文件中

Bird::Bird(QWidget *parent)
    : QWidget{parent}
{

    for(int i=0;i<this->max;i++)
    {
        QString path=QString(":/Image/%1.png").arg(i);
        this->m_Bird_Pix.load(path);
    }

    //设置鸟的尺寸
    this->setFixedSize(this->m_Bird_Pix.width(),this->m_Bird_Pix.height());
}

③将鸟类对象添加到主窗口中

MainScene::MainScene(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MainScene)
{
    ui->setupUi(this);

    this->m_Bird=new Bird;
    //将鸟对象设置到窗口中
    this->m_Bird->setParent(this);

    //设置窗口尺寸
    this->setFixedSize(this->m_Bird->width(),this->m_Bird->height());
}

MainScene::~MainScene()
{
    delete ui;
}

void MainScene::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    //绘制鸟的图像
    painter.drawPixmap(0,0,this->m_Bird->m_Bird_Pix);
}

2.鸟动画实现

鸟类中:设置一个定时器,每0.7秒超时一次,超时后加载小鸟图片,并发出切图信号

class Bird : public QWidget
{
    Q_OBJECT
public:
    explicit Bird(QWidget *parent = nullptr);
    
    QPixmap m_Bird_Pix;//鸟显示的图片
    
    int min=1;//最小值图片下标
    int max=2;//最大值图片下标
    
    QTimer* timer;
    
    //执行动画函数
    void running();
signals:
    //代表正在做动画切图
    void changePix();
    
public slots:
};
Bird::Bird(QWidget *parent)
    : QWidget{parent}
{

    for(int i=0;i<this->max;i++)
    {
        QString path=QString(":/Image/%1.png").arg(i);
        this->m_Bird_Pix.load(path);
    }

    //设置鸟的尺寸
    this->setFixedSize(this->m_Bird_Pix.width(),this->m_Bird_Pix.height());
    
    this->timer=new QTimer(this);
    connect(this->timer,&QTimer::timeout,[=]{
        QString path=QString(":/Image/%1.png").arg(this->min++);
        //超时之后,加载图片
        this->m_Bird_Pix.load(path);
        
        if(this->min>this->max)
        {
            this->min=1;
        }
        //切图
        emit changePix();
    })
}

void Bird::running()
{
    //0.7秒切一次动画
    this->timer->start(70);
}

主程序中:只要小鸟对象发出切图信号,就刷新一次

MainScene::MainScene(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::MainScene)
{
    ui->setupUi(this);

    this->m_Bird=new Bird;
    //将鸟对象设置到窗口中
    this->m_Bird->setParent(this);

    //设置窗口尺寸
    this->setFixedSize(this->m_Bird->width(),this->m_Bird->height());
    
    //启动计时器,开始动画
    this->m_Bird->running();
    //监听鸟在切图的信号
    connect(this->m_Bird,&Bird::changePix,[=]{
        update();
    })
}

3.鼠标拖拽

1.获取鼠标(QMouseEvent)点击的位置相对于全局窗口的坐标(globalPos())

2.获取鸟类窗口的左上角定点位置

3.计算鼠标点击位置到鸟类窗口左上角的相对分量,这一分量是绝对的

void Bird::mousePressEvent(QMouseEvent *e)
{
    this->m_Pox=e->globalPos()-((QWidget*)this->parent())->frameGeometry().topLeft();
}

4.当鼠标拖拽到另一点时,鼠标点击位置可以获取到,相对分量也知道,鸟类窗口的位置即【鼠标点击位置-相对分量】

5.完成鼠标拖拽后,将鸟类窗口位置作为参数,发送窗口移动的信号

void Bird::mouseMoveEvent(QMouseEvent *e)
{
    emit this->moving(e->globalPos()-this->m_Pox);
}

6.主窗口,监听鸟类对象是否发送移动信号,发送信号就移动窗口位置

    //监听鸟的移动信号
    connect(this->m_Bird,&Bird::moving,[=](QPoint point){
            this->move(point);
    });

4.自动移动

1.创建自动移动点位和定时器

    //自动移动位置
    QPoint m_Auto_Pos;
    
    //自动移动定时器
    QTimer* timer;

2.获取主屏幕宽度

    //获取屏幕
    QDesktopWidget* desk=QApplication::desktop();
    int deskWidth=desk->width();

3.自动移位定时器超时,则将自动移动点位的x坐标加5,不断向右移动【当自动移动点位的x坐标超过主屏幕大小时,将自动移动点位的x坐标设置为鸟类窗口宽度的负数】

    this->timer=new QTimer(this);
    timer->start(30);
    
    //超时后将窗口x坐标加5,不断向右移动,超过主屏幕时,将移动位置设为当前窗口宽度的负数
    connect(this->timer,&QTimer::timeout,[=]{
        this->m_Auto_Pos.setX(m_Auto_Pos.x()+5);
        
        if(this->m_Auto_Pos.x()>desk->width())
        {
            this->m_Auto_Pos.setX(-this->width());
        }
        
        this->move(this->m_Auto_Pos);
    };

4.将窗口移动到自动移动点位的位置

【优化】上述代码,鼠标按下时,图像也会自由移动,现优化为鼠标按下时,不移动图像

1.添加鼠标是否按下的标识

    //鼠标按下的状态
    bool mouseDown=false;

2.鼠标按下事件中,将mouseDown置为true,鼠标释放事件中,将mouseDown置为false

void Bird::mouseReleaseEvent(QMouseEvent *e)
{
    this->mouseDown=false;
}

void Bird::mousePressEvent(QMouseEvent *e)
{
    this->mouseDown=true;
    this->m_Pox=e->globalPos()-((QWidget*)this->parent())->frameGeometry().topLeft();
}

3.鼠标按下状态mouseDown=false时,才可以自由移动

    //超时后将窗口x坐标加5,不断向右移动,超过主屏幕时,将移动位置设为当前窗口宽度的负数
    connect(this->timer,&QTimer::timeout,[=]{
        //鼠标不是按下的状态时,才可以自由移动
        if(this->m_Bird->mouseDown==false)
        {
            this->m_Auto_Pos.setX(m_Auto_Pos.x()+5);
        }
        
        if(this->m_Auto_Pos.x()>desk->width())
        {
            this->m_Auto_Pos.setX(-this->width());
        }
        
        this->move(this->m_Auto_Pos);
    };

5.右键菜单

1.创建菜单

    this->m_menu=new QMenu();
    
    connect(this->m_menu->addAction("退出"),&QAction::triggered,[=]{
        exit(0);
    });

2.鼠标按下后,判断按键,如果是右键,则弹出菜单

void Bird::mousePressEvent(QMouseEvent *e)
{
    this->mouseDown=true;
    this->m_Pox=e->globalPos()-((QWidget*)this->parent())->frameGeometry().topLeft();
    
    if(e->button()==Qt::RightButton)
    {
        //将菜单弹到光标位置处
        this->m_menu->popup(QCursor::pos());
    }
}

3.菜单如果消失,也要将鼠标按下状态置为false

void Bird::mousePressEvent(QMouseEvent *e)
{
    this->mouseDown=true;
    this->m_Pox=e->globalPos()-((QWidget*)this->parent())->frameGeometry().topLeft();
    
    if(e->button()==Qt::RightButton)
    {
        //将菜单弹到光标位置处
        this->m_menu->popup(QCursor::pos());
    }
    
    //菜单消失后,将鼠标按下状态置为false
    connect(this->m_menu,&QMenu::aboutToHide,[=]{
        this->mouseDown=false;
    })
}

6.窗口透明化

1.去掉标题栏

     //去掉标题栏
    this->setWindowFlags(Qt::FramelessWindowHint);

2.设置透明窗体

    //设置透明窗体
    this->setAttribute(Qt::WA_TranslucentBackground);

3.窗口设置到顶层(鼠标如果点击,鸟会消失,其实鸟隐藏在页面的下一层,设置之后,鸟永远在页面最顶层,不会消失)

    //窗口设置到顶层(鼠标如果点击,鸟会消失,其实鸟隐藏在页面的下一层,设置之后,鸟永远在页面最顶层,不会消失)
    this->setWindowFlags(this->windowFlags()|Qt::WindowStaysOnTopHint);

 4.设置起始Y位置,从主窗口中间出现

    //设置起始Y位置,从主窗口中间出现
    this->m_Auto_Pos.setY(desk->height()*0.5-this->m_Bird->height());

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

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

相关文章

云技术-docker

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团…

《解锁计算机专业宝藏:核心编程语言与学习资料全解析》

在当今数字化浪潮汹涌澎湃、技术迭代日新月异的时代&#xff0c;计算机专业宛如一座蕴藏无尽宝藏与无限机遇的神秘殿堂&#x1f3f0;。对于莘莘学子而言&#xff0c;精准掌握核心编程语言&#xff0c;并手握优质学习资料&#xff0c;恰似寻得开启这扇殿堂大门的秘钥&#xff0c…

27加餐篇:gRPC框架的优势与不足之处

gRPC作为一个现代的、开源的远程过程调用(RPC)框架,在多个方面都展现了其优雅之处,同时也存在一些不足之处。这篇文章我们就相对全面的分析一下gRPC框架那些优雅的地方和不足的地方。 优雅的地方 gRPC作为一个RPC框架,在编码、传输协议已经支持多语言方面都比较高效,下…

Leetcode打卡:交替组II

执行结果&#xff1a;通过 题目&#xff1a;3208 交替组II 给你一个整数数组 colors 和一个整数 k &#xff0c;colors表示一个由红色和蓝色瓷砖组成的环&#xff0c;第 i 块瓷砖的颜色为 colors[i] &#xff1a; colors[i] 0 表示第 i 块瓷砖的颜色是 红色 。colors[i] 1 …

在Windows下编译支持https的wsdl2h

下载源码 在官网下载源码 安装Openssl 下载OpenSSL并安装&#xff0c;安装完成后需要将OpenSSL的路径添加到环境变量中 配置VS 1、打开工程 2、因为前面安装的OpenSLL是64位的&#xff0c;因此需要创建一个X64的配置 打开配置管理器&#xff0c;然后选择新建&#xff0…

利用Prompt工程为LLM提升推理能力

利用Prompt工程为LLM提升推理能力 基于策略的推理详解ReAct: 推理与行动思维链&#xff1a;逐步解决问题反思&#xff1a;深入分析和自我审查与代理架构的集成实际应用代码附录 众所周知&#xff0c;一个精心设计的Prompt能够显著增强大型语言模型&#xff08;LLMs&#xff09;…

[C++ 核心编程]笔记 4.1 封装

4.1.1 封装的意义 封装是C面向对象三大特性之一 封装的意义: 将属性和行为作为一个整体&#xff0c;表现生活中的事物将属性和行为加以权限控制 封装意义一: 在设计类的时候&#xff0c;属性和行为写在一起&#xff0c;表现事物 语法: class 类名{ 访问权限: 属性 /行为 }…

基于Qt实现的自定义树结构容器:设计与应用

在Qt框架中&#xff0c;尽管其提供了许多强大的容器类&#xff08;如 QList, QMap, QTreeWidget 等&#xff09;&#xff0c;但缺少一个通用的、灵活的树结构容器&#xff0c;直接支持多层级数据管理。为了满足这些需求&#xff0c;本文设计并实现了一个可复用的自定义树结构容…

Web登录页面设计

记录第一个前端界面&#xff0c;暑假期间写的&#xff0c;用了Lottie动画和canvas标签做动画&#xff0c;登录和注册也连接了数据库。 图片是从网上找的&#xff0c;如有侵权私信我删除&#xff0c;谢谢啦~

钟睒睒的“傲慢与偏见”

文章内容根据网络内容整理形成 最近&#xff0c;钟睒睒关于绿瓶水不适合长期饮用的言论&#xff0c;在网上引起了一番新的热议&#xff0c;让刚平静不久的包装饮用水竞争&#xff0c;再次掀起一阵波澜&#xff0c;同时&#xff0c;其对于企业家直播带货的等系列看法&#xff0c…

【ArcGISPro】使用AI提取要素-土地分类(sentinel2)

Sentinel2数据处理 【ArcGISPro】Sentinel-2数据处理-CSDN博客 土地覆盖类型分类 处理结果

【技术文档:技术传播的灯塔】

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

Qt-系统相关(2)多线程网络

Qt多线程 在 Qt 中&#xff0c;多线程的处理⼀般是通过 QThread类 来实现。 QThread 代表⼀个在应⽤程序中可以独⽴控制的线程&#xff0c;也可以和进程中的其他线程共享数据。 QThread 对象管理程序中的⼀个控制线程。 QThread 常⽤ API&#xff1a; 使用线程 关于创建线程…

永久免费使用最好的Markdown编辑器——Typora

介绍 Typora 是一款轻量级的 Markdown 编辑器&#xff0c;其最为出众的特点是&#xff1a; 所见即所得。 Typora 于2021年11月23日推出了第一个正式版&#xff0c;并转为收费。不过价格也算合理&#xff0c;89元/3台设备&#xff0c;为一次买断制。 直到2022年年中&#xff0…

Linux环境实现c语言编程

Linux环境实现c语言编程 准备工作 准备一台Linux虚拟机/机器 操作流程 打开Linux机器 打开终端 查看是否有GCC编译器 GCC是什么 GCC是GNU编译器集合&#xff08;GNU Compiler Collection&#xff09;的简称。它是一套免费的开源编程语言编译器&#xff0c;支持多种编程语…

VTK中对于相机camera的设置

1. 相机的核心属性 在 VTK 中&#xff0c;vtkCamera 的核心属性有默认值。如果你不设置这些属性&#xff0c;相机会使用默认值来渲染场景。 Position&#xff08;默认值&#xff1a;(0, 0, 1)&#xff09;&#xff1a; 默认情况下&#xff0c;相机位于 Z 轴正方向的 (0, 0, 1)…

glog在vs2022 hello world中使用

准备工作 设置dns为阿里云dns 223.5.5.5&#xff0c;下载cmake&#xff0c;vs2022&#xff0c;git git clone https://github.com/google/glog.git cd glog mkdir build cd build cmake .. 拷贝文件 新建hello world并设置 设置预处理器增加GLOG_USE_GLOG_EXPORT;GLOG_NO_AB…

Python开发环境搭建+conda管理环境

下载Miniconda 推荐从清华镜像下载安装包 Index of /anaconda/miniconda/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 打开网页后&#xff0c;下拉到最后找到Miniconda3-latest前缀的文件&#xff0c;或者网页中直接搜索Miniconda3-latest&#xff0c;都可以找…

深度学习:GPT-2的MindSpore实践

GPT-2简介 GPT-2是一个由OpenAI于2019年提出的自回归语言模型。与GPT-1相比&#xff0c;仍基于Transformer Decoder架构&#xff0c;但是做出了一定改进。 模型规格上&#xff1a; GPT-1有117M参数&#xff0c;为下游微调任务提供预训练模型。 GPT-2显著增加了模型规模&…

C++设计模式-策略模式-StrategyMethod

动机&#xff08;Motivation&#xff09; 在软件构建过程中&#xff0c;某些对象使用的算法可能多种多样&#xff0c;经常改变&#xff0c;如果将这些算法都编码到对象中&#xff0c;将会使对象变得异常复杂&#xff1b;而且有时候支持不使用的算法也是一个性能负担。 如何在运…