Qt学习:综合案例应用-上(翻金币小游戏)

2023-05-16

本案例是对Qt的基本控件,事件处理,资源文件的使用等知识的综合应用。以及一些开发思想和逻辑控制。
首先了解下案例的文件构成
头文件:
mainwindow.h
chooselevelscene.h
playscene.h
mypushbutton.h
mycoin.h
dataconfig.h
源文件:
main.cpp
mainwindow.cpp
chooselevelscene.cpp
playscene.cpp
mypushbutton.cpp
mycoin.cpp
dataconfig.cpp
资源文件
res.qrc 其中添加了图片,音频资源
新建资源文件后,添加前缀,添加文件,构建。 提前将资源文件加载好。

初步实现是搭建基本的场景,先设计出主界面。
mainwindow.h


public:

    virtual void  paintEvent(QPaintEvent *event);
    ChooseLevelScene *chooseScence = NULL;

该文件中主要是这两句, 第一句实现在cpp通过重写绘图事件,构建主场景的显示界面。
第二句提前定义好第二个选择场景。在构造函数中new出该场景对象实现管理与切换。
mainwindow.cpp

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
   //设置固定大小
    setFixedSize(320,588);
    //设置窗口图标
    setWindowIcon(QIcon(":/image/2.jpg"));
    //设置窗口标题
    //setWindowTitle("打小猪");
    setWindowTitle("pig");
    //退出按钮
    connect(ui->actionquit,&QAction::triggered,[=](){
        this->close();
    });

    //准备开始按钮的音效
    //QSound *startSound = new QSound(":/s/sound/02.wav",this);
    //开始按钮
    MyPushButton  *startBtn = new MyPushButton(":/image/3.jpg");
    startBtn->setParent(this);
    startBtn->move(this->width()*0.5-startBtn->width()*0.5,this->height()*0.7);
   chooseScence = new ChooseLevelScene;
            //监听信号
     connect(chooseScence,&ChooseLevelScene::chooseSceneBack,this,[=](){
        this->setGeometry(chooseScence->geometry());
        chooseScence->hide();
        this->show();
        });

    connect(startBtn,&MyPushButton::clicked,[=](){
      //  qDebug()<<"press start";
       //播放开始音效资源
      // startSound->play();
      //  QSound::play(":/s/sound/02.wav");
        startBtn->zoom1();
        startBtn->zoom2();

        //延时进入关卡中
        QTimer::singleShot(500,this,[=](){
        //设置chooseScence场景的位置
        chooseScence->setGeometry(this->geometry());
        //进入到选择关卡的场景中
            this->hide();
            chooseScence->show();
        });
    });
}

最上面一小段是设置界面大小,标题,图标,以及菜单栏上的退出按钮

另外,本案例中的connect基本都用了lambda表达式,这样就省去了写槽函数。主函数的代码量增大,可读性差了些。 但是免去了定义许多槽函数。

    connect(ui->actionquit,&QAction::triggered,[=](){
        this->close();
    });

接下来注释掉的语句用来建立音效对象。
下来是使用代码建立开始按钮。 设置好它的对象树,并移到合适位置。 (此处的自定义按钮的构造函数中实现了传入图标及按钮大小和图标的设置 )

新建出选择场景用来切换。

两个信号与槽连接实现了开始按钮切换场景和第二个场景中返回按钮返回当前界面
在开始按钮按下中,自定义按扭还封装了弹跳的动画接口,实现按钮特效。
同时,使用定时器

  QTimer::singleShot(500,this,[=](){
        //设置chooseScence场景的位置
        chooseScence->setGeometry(this->geometry());
        //进入到选择关卡的场景中
            this->hide();
            chooseScence->show();
        });

实现了场景切换的延时。

 chooseScence->setGeometry(this->geometry());

用来保持切换场景时位置不改变

void  MainWindow::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    QPixmap pix;
    pix.load(":/image/7.jpg");
    //指定长宽
    painter.drawPixmap(0,0,this->width(),this->height(),pix);
    //在背景上加图标背景
    pix.load(":/image/1.jpg");
    //缩放
    pix=pix.scaled(pix.width()*0.5,pix.width()*0.5);
    painter.drawPixmap(10,30,pix);
}

通过重写绘图事件在主窗口中绘制了背景。 创建画家,装载图片,缩放,绘制。

自定义按钮的构造函数和对外接口提供了一些按钮的自定义功能
mypushbutton.h

class MyPushButton : public QPushButton
{
    Q_OBJECT
public:
   // explicit MyPushButton(QWidget *parent = nullptr);
    //  正常显示的图片路径     按下后的图片路径
    MyPushButton(QString normalImg,QString pressImg = "");
    
    QString normalImgPath;
    QString pressImgPath;
    
    //弹跳特效
    void zoom1();  //向下跳
    void zoom2();  //向上跳

    virtual void mousePressEvent(QMouseEvent *e);
    virtual void mouseReleaseEvent(QMouseEvent *e);

该按钮继承自QPushButton类,自定义了构造函数,重写了鼠标按下和弹起事件,定义了两个弹跳特效的函数,两个QString成员用来保存构造时传入的图片路径

mypushbutton.cpp

 MyPushButton::MyPushButton(QString normalImg,QString pressImg )
 {
    this->normalImgPath = normalImg;
    this->pressImgPath = pressImg;

    QPixmap pix;
    bool ret = pix.load(normalImg);
    if(!ret)
    {
        qDebug()<<"load fail";
        return ;
    }
    //设置按钮依据图片固定大小
    this->setFixedSize(pix.width()*0.3,pix.height()*0.3);
    //设置不规则样式
    this->setStyleSheet("QPushButton{border:0px;}");    
    //设置图标
    this->setIcon(pix);
    //设置图标大小
    this->setIconSize(QSize(pix.width()*0.3,pix.height()*0.3));

 }

 void MyPushButton::zoom1()
 {
    QPropertyAnimation *animation = new QPropertyAnimation(this,"geometry");
    //设置动画时间间隔
    animation->setDuration(200);

    //起始位置
    animation->setStartValue(QRect(this->x(),this->y(),this->width(),this->height()));
    //结束位置
    animation->setEndValue(QRect(this->x(),this->y()+10,this->width(),this->height()));
    //设置弹跳曲线
    animation->setEasingCurve(QEasingCurve::OutBounce);
    //执行动画
    animation->start();
 }

void MyPushButton::zoom2()
{
 QPropertyAnimation *animation = new QPropertyAnimation(this,"geometry");
    //设置动画时间间隔
    animation->setDuration(200);

    //起始位置
    animation->setStartValue(QRect(this->x(),this->y()+10,this->width(),this->height()));
    //结束位置
    animation->setEndValue(QRect(this->x(),this->y(),this->width(),this->height()));
    //设置弹跳曲线
    animation->setEasingCurve(QEasingCurve::OutBounce);
    //执行动画
    animation->start();
}


 void MyPushButton::mousePressEvent(QMouseEvent *e)
 {
    if(this->pressImgPath != "")//传入的状态不为空,说明要切换图片
    {
        QPixmap pix;
        bool ret = pix.load(this->pressImgPath);
        if(!ret)
        {
            qDebug()<<"load fail";
        }

        this->setFixedSize(pix.width()*0.3,pix.height()*0.3);

        this->setStyleSheet("QPushButton{border:0px}");

        this->setIcon(pix);

        this->setIconSize(QSize(pix.width()*0.3,pix.height()*0.3));
    }
    return QPushButton::mousePressEvent(e);
 }
 void MyPushButton::mouseReleaseEvent(QMouseEvent *e)
 {

  if(this->pressImgPath != "")//传入的状态不为空,说明要切换图片
    {
        QPixmap pix;
        bool ret = pix.load(this->normalImgPath);
        if(!ret)
        {
            qDebug()<<"load fail";
        }

        this->setFixedSize(pix.width()*0.3,pix.height()*0.3);

        this->setStyleSheet("QPushButton{border:0px}");

        this->setIcon(pix);

        this->setIconSize(QSize(pix.width()*0.3,pix.height()*0.3));
    }
    return QPushButton::mouseReleaseEvent(e);
 }

代码多是重复的,核心一个是设置按钮大小和图标
另一个是设置动画。

chooselevelscene.h

  virtual void paintEvent(QPaintEvent *event);
    PlayScene *play;
signals:
    void chooseSceneBack();

主要就是重写绘图事件,另一个是定一个信号传给主界面响应。还有是定义第三个场景用来管理。

chooselevelscene.cpp

ChooseLevelScene::ChooseLevelScene(QWidget *parent) : QMainWindow(parent)
{

    //配置选择关卡场景
    this->setFixedSize(320,588);

    this->setWindowIcon(QPixmap(":/image/2.jpg"));

    this->setWindowTitle("choose sceene");

    //创建菜单栏

    QMenuBar  *bar = menuBar();
    setMenuBar(bar);

    QMenu *startMenu = bar->addMenu("start");

    QAction *quitAction = startMenu->addAction("quit");

    connect(quitAction,&QAction::triggered,[=](){
        this->close();
    });

    //返回按钮
    MyPushButton *backBtn = new MyPushButton(":/image/1.jpg",":/image/2.jpg");
    backBtn->setParent(this);
    backBtn->move(this->width()-backBtn->width(),this->height()-backBtn->height());

    connect(backBtn,&MyPushButton::clicked,[=](){
       // backBtn->zoom1();
       //告诉主场景 我返回了,主场景监听chooselevelscene的返回按钮
       //自定义信号
       //延时发送信号

        QTimer::singleShot(300,this,[=](){

        //进入到选择关卡的场景中
        emit  this->chooseSceneBack();
        });

    });

    //创建选择关卡的按钮
    for(int i =0;i<20;i++)  //一个循环写出一个矩阵
    {
        MyPushButton *menuBtn = new MyPushButton(":/image/2.jpg");
        menuBtn->setParent(this);
        menuBtn->move(25+i%4*70,130+i/4*70);

        connect(menuBtn,&MyPushButton::clicked,[=](){
            qDebug()<<i+1;

            //进入到游戏场景

            this->hide();
            play = new PlayScene(i+1);
            play->setGeometry(this->geometry());
            play->show();

            connect(play,&PlayScene::chooseSceneBack,[=](){
                this->setGeometry(play->geometry());
                this->show();
                delete play;
                play = NULL;
            });
        });
        QLabel *label = new QLabel;
        label->setParent(this);
        label->setFixedSize(menuBtn->width(),menuBtn->height());
        QFont font;
        font.setFamily("华文新魏");
        font.setPointSize(20);
        label->setFont(font);
        label->setStyleSheet("color:blue;");  //设置字体颜色

        label->setText(QString::number(i+1));
       // label->setFont(QFont());
        label->move(25+i%4*70,130+i/4*70);

        label->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
        //label 把信号屏蔽了,  把鼠标穿透事件捕获了 ,所以要允许穿透
        label->setAttribute(Qt::WA_TransparentForMouseEvents);
    }
}

设置标题,图标等,新建菜单栏,添加动作。 创建返回按钮。 返回按钮中延时发送返回信号。

创建选择关卡的按钮时用循环控制,新建20个选关按钮。 每个按钮连接信号与槽,切到第三个场景。

通过QLabel标签 设置关卡号。 同时要通过

        //label 把信号屏蔽了,  把鼠标穿透事件捕获了 ,所以要允许穿透
        label->setAttribute(Qt::WA_TransparentForMouseEvents);

将鼠标事件穿透给按钮

dataconfig.h

    explicit dataConfig(QObject *parent = nullptr);
    QMap<int,QVector<QVector<int>>>mData;

dataconfig.cpp

dataConfig::dataConfig(QObject *parent) : QObject(parent)

{
    int array1[4][4] ={ {1,1,1,1},
                        {1,1,0,1},
                        {1,0,0,0},
                        {1,1,0,1} };
    QVector<QVector<int>>v;

    for(int i=0;i<4;i++)
    {
        QVector<int>v1;
        for(int j=0;j<4;j++)
        {
            v1.push_back(array1[i][j]);
        }
        v.push_back(v1);
    }
    mData.insert(1,v);

     int array2[4][4] ={ {1,1,0,1},
                        {1,1,0,1},
                        {1,1,0,0},
                        {1,1,0,1} };
    v.clear();

    for(int i=0;i<4;i++)
    {
        QVector<int>v1;
        for(int j=0;j<4;j++)
        {
            v1.push_back(array2[i][j]);
        }
        v.push_back(v1);
    }
    mData.insert(2,v);
    ……
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt学习:综合案例应用-上(翻金币小游戏) 的相关文章

  • Gazebo——仿真平台搭建(基于Ubuntu20.04)

    目录 Gazebo安装配置 创建仿真环境 仿真使用 Rviz查看摄像头采集的信息 Kinect仿真 问题解决 xff1a 1 gazebo SpawnModel Failure model name mrobot already exist
  • 单片机要学多久可以找到工作?能找到哪类的工作

    单片机学多久能工作 单片机学好了能应聘什么工作 xff1f 从事单片机开发10年 xff0c 我见证了这个行业的成长 xff0c 最明显的就是这几年的工资涨幅 大家好 xff0c 我是小哥 xff0c 10年前我还是个对前景充满憧憬的小屌丝
  • 互联网企业部分面试笔试真题以及考察知识点总结(一)

    1 static的作用 1 1用static关键字修饰的静态变量 静态变量属于类 xff0c 在内存中只有一个复制 xff0c 只要静态变量所在的类被加 载 xff0c 这个静态变量就会被分配空间 1 2 static成员方法 Java中提
  • 史上最全网址导航大全,让世上没有找不到的好东西

    收录的导航网址大全 好用和常用的网址几乎都在里面 个人喜欢往浏览器书签收藏夹里塞喜欢的干货和网站 xff0c 以至于收藏夹里有着几千条网址 xff0c 所以比较喜欢导航 xff0c 但是浏览器原生自带的导航又太low 所以一般自己设置打开浏
  • HTTP的认证方式之DIGEST 认证(摘要认证)

    核心步骤 xff1a 步骤 1 xff1a 请求需认证的资源时 xff0c 服务器会随着状态码 401Authorization Required xff0c 返回带WWW Authenticate 首部字段的响应 该字段内包含质问响应方式
  • 相机标定评价标准

    相机标定的实验一般根据图像数据的类型分为两种 xff1a 1 仿真实验 2 实际场景的操作性实验 目前为止 xff0c 还没有形成一套完善的用于评价相机标定方法的标准体系 xff0c 通常采用的评价准则如下 xff1a 1 标定方法是否具有
  • ubuntu下串口工具的安装与使用

    1 概述 作为一个嵌入式开发人员 xff0c 串口是开发过程中不可或缺的工具之一 xff0c window下有各种各样的串口工具 xff0c 使用起来很方便 xff0c 这里不再做过多陈述 xff0c 这里主要介绍Ubuntu 16 04
  • Ubuntu查看文件大小或文件夹大小

    Ubuntu查看文件大小或文件夹大小 一 查看文件大小 查看文件大小的命令 xff1a ls l filename 会在终端输出 xff1a rw r r 1 root root 2147483648 Mar 5 09 39 filetem
  • 结构体数据对齐

    结构体数据对齐 结构体数据对齐 xff0c 是指结构体内的各个数据对齐 在结构体中的第一个成员的首地址等于整个结构体的变量的首地址 xff0c 而后的成员的地址随着它声明的顺序和实际占用的字节数递增 为了总的结构体大小对齐 xff0c 会在
  • 2016你配得上更好地自己

    传统里我一直觉得过完春节才是一年结束的时候 xff0c 但是现在慢慢习惯阳历的计算 xff0c 2017年1月1日 xff0c 看着空间里面新年祝福和期待 xff0c 突然觉得这才是过年 2016年就这样走了 xff0c 以后我再也回不到2
  • 树莓派镜像备份与恢复文章

    在做完下属步骤以后 xff0c 需要考虑分区表 xff0c 将分区表复制到镜像里 xff0c 否则系统无法启动 xff0c 而且还要回利用gparted dev loop0以及fdisk l dev loop0等命令 xff0c 查看分区类
  • 在树莓派上将现有系统复制到新存储卡(转载 )

    在树莓派上将现有系统复制到新存储卡 xff08 转载 xff09 http www eeboard com bbs thread 39663 1 1 html 最初 xff0c 使用树莓派的时候 xff0c 也许也只是为了新鲜 xff0c
  • 【c/c++】单链表、头指针、头结点、首元节点

    链表中第一个结点的存储位置叫做头指针 xff0c 那么整个链表的存取就必须是从头指针开始进行了 之后的每一个结点 xff0c 其实就是上一个的后继指针指向的位置 这里有个地方要注意 xff0c 就是对头指针概念的理解 xff0c 这个很重要
  • VINS-mono学习总结

    Vins mono是一个后端基于非线性优化的 单目与IMU紧耦合的融合定位算法 整体 xff1a 1 预处理模块 视觉 xff1a 特征点提取与追踪 IMU xff1a 惯性解算与误差状态分析 计算预积分量 2 初始化模块 xff08 旋转
  • Fast-lio个人总结

    Lidar第一帧作为基坐标 1 lidar原始数据预处理默认不提取特征 xff0c 对原始数据间隔式 xff08 间隔3个点 xff09 降采样提取 2 imu初始化 惯性解算 误差分析 状态 协方差预测 3 Lidar与imu时间状态对齐
  • 在rviz中使用键盘控制burger

    启动语句 roslaunch turtlebot3 fake turtlebot3 fake launch 启动rviz 话题通信 roslaunch turtlebot3 teleop turtlebot3 teleop key laun
  • shell脚本中=左右的空格问题

    赋值语句等号两边不能有空格 xff1a i 61 1 或i 61 i 43 1 而字符串比较 xff0c 等号两边必须有空格 if a 61 b 比较时 xff0c if a xxx b 中括号前后一定要加空格否则会报错xxx 61 eq
  • freertos.axf: Error: L6218E: Undefined symbol xTaskGetSchedulerState (referred from delay.o).

    今天移植了一下FreeRTOS xff0c 出现了freertos axf Error L6218E Undefined symbol xTaskGetSchedulerState referred from delay o xff0c 这
  • vnc桌面配置及黑屏问题解决

    一 vnc桌面配置 登入需要远程帐号下修改 vnc xstartup 如配置root远程桌面 vi vnc xstartup 原内容如下 xff1a xff3b x etc vnc xstartup xff3d amp amp exec e
  • 华清嵌入式--入学篇

    当初在学习嵌入式的时候 xff0c 就知道嵌入式门槛高 xff0c 需要的知识比较多 工作了4年多时间 xff0c 确实感觉还是刚入门的感觉 xff0c 焊接 调试 原理图 PCB 模电 数电 c语言 数据结构 单片机 linux等知识比价

随机推荐

  • 20.华清嵌入式--数据结构入门

    从今天开始正式开始学习数据结构与算法 从今天开始正式开始学习数据结构与算法 从上面的框图也可以从整体上把握数据结构的关键知识点 xff0c 不管是简单的顺序表还是栈 xff0c 树等 xff0c 学习的方法都是一样的他们的操作也都是无非都是
  • 35.Linux应用层开发---线程

    一 线程的概念和使用 1 线程的概念 为了进一步减少处理器的空转时间 xff0c 支持多处理器以及减少上下文切换开销 xff0c 进程在演化中出现了另外一个概念线程 它是进程内独立的一条运行路线 xff0c 是内核调度的最小单元 xff0c
  • 36.Linux 应用层开发--进程间通讯

    最近因为项目原因耽误了一些时间 xff0c 导致进程间的通讯一直没有来的及学习及整理 在我们之前学过进程相关的概念和操作 xff0c 还学习了轻量级的进程的线程 xff0c 在我们之后的开发和面试中 xff0c 多线程 xff0c 多进程开
  • 树莓派4 ubuntu22.04LTS整合Intel Realsense深度相机

    树莓派4 ubuntu22 04LTS整合Intel Realsense深度相机 文章目录 树莓派4 ubuntu22 04LTS整合Intel Realsense深度相机前言一 为什么不使用Docker安装或使用官方教程安装 xff1f
  • 串口打印调试信息(干货)

    printf重定向到串口 上代码 xff0c 这里用到的是hal库 xff0c 标准库改以下函数就行 span class token macro property span class token directive keyword in
  • 相电流与线电流有什么区别

    相电流和线电流的区别 xff0c 主要看负载的连接方法 xff0c 如果是星型接法 xff0c 相电流和线电流相同 xff0c 线电压是相电压的开方3倍 如果负载是三角形接法 xff0c 那么 xff0c 线电流是相电流的开方3倍 xff0
  • STM32f103c8t6的定时器配置定时中断

    span class token comment 时间计算公式 span Tout span class token operator 61 span xff08 xff08 arr span class token operator 43
  • 集成学习方法

    概述 集成学习 xff0c 是将几个泛化能力差的模型相结合 xff0c 组成泛化能力强的模型 常见的做法就是分别训练几个模型 xff0c 然后再将多个模型的输出组合 xff0c 形成最终输出 xff0c 也称为模型平均的效果 类似的策略都称
  • (Java)常规技术面试题

    Java基础部分 1 Java 的 一次编写 处处运行 如何实现 xff1f JAVA之所以能实现 一次编译 xff0c 到处运行 xff0c 是因为JAVA在每个系统平台上都有 JAVA虚拟机 xff08 JVM xff09 xff0c
  • ESP8266烧写固件提示等待上电

    环境 供电电压 xff1a span class token number 5 span V 模块 xff1a 正点原子ATK span class token operator span ESP span class token oper
  • 嵌入式面试刷题

    1 表示一年有多少秒 define SECONDS PER YEAR 606024 365 UL 2 写一个标准宏 MIN define MIN A B A lt 61 B A B 3 指针数组 int a 10 优先级高所以是a 10 数
  • ubuntu18配置ftp

    安装ftp 修改文件 sudo gedit etc vsftpd conf span class token comment Example config file etc vsftpd conf span span class token
  • win11切换win10资源管理器

    HKEY LOCAL MACHINE SOFTWARE Microsoft Windows CurrentVersion Shell Extensions 右键 Blocked 选择 新建 字符串值 名称为 e2bf9676 5f8f 43
  • 联想小新pro13笔记本外接显示屏没信号

    step1 关机 step2 拔下电源 step3 安住 fn 43 s 43 v键 xff0c 开机 xff08 开不了机 xff0c 我重复了几次 xff09 step4 插电源开机 xff0c 扩展屏幕正常
  • C51内存类型

    bdata bdata内存类型只能用于声明变量 您不能声明bdata函数 该存储器使用8位地址直接访问 xff0c 是8051的片内位可寻址RAM 用bdata类型声明的变量是位可寻址的 xff0c 可以用位指令读写 code 代码存储器类
  • MQTT问题

    是否存在c gt ping outstanding 61 1 的后一秒就触发TimerIsExpired amp c gt last received span class token keyword int span span class
  • Failed to start apt-news.service Failed to start esm-cache.service

    luozw 64 luozw vpc etc apt apt conf d span class token function sudo span span class token function apt get span update
  • stm中断优先级理解+抢占优先级和相应优先级

    一 抢占优先级比子优先级的优先权更高 xff0c 这意味抢占优先级更高的中断会先执行 xff0c 而不管子优先级的优先权 xff0c 数值越低优先级越高 二 同理 xff0c 如果抢占优先级相同 xff0c 那么就会比较子优先级 xff0c
  • Realsense D435基于ROS跑通ORBSLAM2

    Realsense D435基于ROS跑通ORBSLAM2 系统ubuntu16 04 ROS Kinetic 相机RealsenseD435 SLAM系统 xff1a ORBSLAM2 一 安装Realsense的SDK 官方链接 htt
  • Qt学习:综合案例应用-上(翻金币小游戏)

    本案例是对Qt的基本控件 xff0c 事件处理 xff0c 资源文件的使用等知识的综合应用 以及一些开发思想和逻辑控制 首先了解下案例的文件构成 头文件 xff1a mainwindow h chooselevelscene h plays