相随与欢-课程设计

相随与欢

大一下-面向对象课程设计-彩色泡泡机题目详解

与欢行

一、题目与需求分析:

基于Qt框架的GUI设计与实现

需求:

1、绘制泡泡(颜色、大小等配置信息随机产生)

2、点击游戏区域即可产生泡泡。

3、泡泡会向上漂浮离开(速度随机)。

二、具体实现:

A、泡泡绘制类Bubble的设计

bubble.h
#ifndef BUBBLE_H
#define BUBBLE_H

//本类为泡泡的实现类
//采用面向对象思想设计泡泡类并通过具体算法设计将其实现
//2021/6/17 行
//For 欢
//不辞青山,相随与共

#include <QWidget>
#include<QMouseEvent>  //鼠标事件类头文件
#include<QPainter>  //绘图工具头文件
#include<QPaintEvent>  //绘图事件头文件
#include<QPropertyAnimation>  //属性动画头文件  property:属性
#include<QDebug>     //调试输出信息库
#include <QTime>     //随机数强依赖库

QT_BEGIN_NAMESPACE
namespace Ui { class Bubble; }
QT_END_NAMESPACE

class Bubble : public QWidget
{
    Q_OBJECT

public:
    Bubble(int newR,int newX,int newY,QWidget *parent = nullptr);    //参数分别为:
    ~Bubble();
    void setColor(QColor color);  //颜色设置接口
    void paintEvent(QPaintEvent *event);  //绘制事件 泡泡的主要绘制算法实现在此
    void own_show();
private:
    Ui::Bubble *ui;
    QPropertyAnimation *BubbleAnimation;  //数据成员 指针 对象  属性动画类  对象指针   泡泡的漂浮动画
    int x;  //泡泡的X坐标  鼠标点击位置的横坐标  event->pos().x()
    int y;  //泡泡的Y坐标
    int radius;  //半径 通过随机数产生  //泡泡的半径
    QColor m_bubbleColor;  //泡泡的颜色   随机设置RGB通道值
};
#endif // BUBBLE_H
bubble.cpp
#include "bubble.h"
#include "ui_bubble.h"


//通过参数列表进行初始化
//常数据成员必须通过参数列表进行初始化
Bubble::Bubble(int newR,int newX,int newY,QWidget *parent)   //构造函数  构造泡泡图形
    : QWidget(parent)
    , ui(new Ui::Bubble)
    ,x(newX)
    ,y(newY)
    ,radius(newR)
{
    ui->setupUi(this);   //自带的  初始化UI
    //通过调整窗体属性
    //this即当前的对象自身  而当前这个对象本质上是一个widget  是一个页面  通过进行相关参数的调节  将其变为泡泡‘

    //setFixedSize()   设置窗口固定大小
    this->setFixedSize(QSize(80, 80));   //设置固定的大小  泡泡的最大值

    //setWindowFlags   设置窗口属性
    //Qt::FramelessWindowHint无边框化,移动,大小调整
    this->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool);   //设置窗口标志  不带标题栏边框

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

    // 控件显示完关闭后自动删除;
    //this->setAttribute(Qt::WA_DeleteOnClose);  //用于设置各种窗口小部件(widget)的属性。

    //参数解释:动画作用的对象  动画涉及更改的属性  pos:position 位置
    this->BubbleAnimation = new QPropertyAnimation(this, "pos");   //初始化动画成员
}

Bubble::~Bubble()    //析构函数
{
    delete ui;
}

void Bubble::setColor(QColor color)   //颜色更改成员函数
{
    this->m_bubbleColor=color;     //QColor为颜色对象  可以通过RGB/HSV 规则值进行设置
}


//绘制泡泡的图案  画画函数
void Bubble::paintEvent(QPaintEvent *event)   //绘图事件函数 在构造本类对象时自动调用  用于图形的绘制
{
    //画画需要工具(笔和画刷)  笔用于勾勒线条 画刷用于上色   同时还要知道画布是什么
    //QPainter 画笔名(绘图位置)
    QPainter painter(this);   //Qpainter是一个绘图工具 相当于画笔/画刷

    painter.setRenderHint(QPainter::Antialiasing);    //这一句是固定用法 用于图形反走样、抗锯齿   百度查到的

    //void QPainter::setPen ( const QPen & pen )
    //设置新的绘图工具画笔。
    //pen定义了如何绘制线和轮廓,并且它也定义了文本颜色。
    painter.setPen(QPen(m_bubbleColor,10));   //设置画笔  如果是NoPen的话 绘制出来的图案没有边框(界)  勾勒

    //void QPainter::setBrush ( BrushStyle style )
    //设置绘图工具的画刷为黑色和特定的style。
    //painter.setBrush(QBrush(m_bubbleColor));   //设置画刷   为画刷设置颜色  用于给泡泡上色  色彩通过随机的RGB通道值实现

    //联想笔画  写一个字是不是需要笔画和顺序
    //QPainterPath 类(绘图路径)提供了一个容器,用于绘图操作,可以创建和重用图形形状。
    QPainterPath bubblePath;   //泡泡绘制路径
    //path.drawEllipse(x, y, r, r);
    //Ellipse 椭圆(圆)
    bubblePath.addEllipse(QPoint(40, 40), radius, radius);   //将一个圆形添加到绘图路径中
    painter.drawPath(bubblePath);  //绘制图形路径
}

//自己的show方法
void Bubble::own_show()
{
    QWidget::show();

    QTime time;
    time= QTime::currentTime();
    qsrand(time.msec()+time.second()*1000);
    int v = 2000+qrand() % 3000;    //随机速度
    int exc_x = 200+qrand() % 700;    //随机速度
    int control = qrand() % 2;    //控制模式
    this->BubbleAnimation->setDuration(v);   //设置动画持续时长  参数为一个整形数据   时长随机  时长相当于速度
    this->BubbleAnimation->setStartValue(QPoint(x, y));
    if(control==0)
    {
        qDebug()<<"模式0向上漂浮";
        this->BubbleAnimation->setEndValue(QPoint(x+exc_x, -1000));    //设置结束位置  两点确定一线嘛
    }
    else if(control==1)
    {
        qDebug()<<"模式1向下漂浮";
        this->BubbleAnimation->setEndValue(QPoint(x-exc_x, 2000));    //设置结束位置  两点确定一线嘛
    }
     //设置动画的初始值  由于是一个属性动画 更改的是pos(位置)属性  所以初始值应该是位置(坐标)  QPoint
//    this->BubbleAnimation->setEndValue(QPoint(x+200, -500));    //设置结束位置  两点确定一线嘛
    BubbleAnimation->setEasingCurve(QEasingCurve::InOutQuad);   //这个属性保留了动画的缓和曲线  文档看到的
    this->BubbleAnimation->start();   //动画开始
}

B、游戏界面game类的设计与实现

game.h
#ifndef GAME_H
#define GAME_H

#include <QWidget>
#include<QMouseEvent>
#include"bubble.h"

namespace Ui {
class Game;
}

class Game : public QWidget
{
    Q_OBJECT

public:
    explicit Game(QWidget *parent = nullptr);
    ~Game();
    void mousePressEvent(QMouseEvent *event);   //鼠标事件

private:
    Ui::Game *ui;
};

#endif // GAME_H
game.cpp
#include "game.h"
#include "ui_game.h"

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

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

void Game::mousePressEvent(QMouseEvent *event)
{
    QPoint Pos = event->pos();   //显示鼠标点击的位置  以坐标形式呈现
    qDebug() << "当前鼠标的位置:" << Pos;  //输出鼠标所点击位置的坐标

    //产生一堆随机数
    QTime time;
    time= QTime::currentTime();
    qsrand(time.msec()+time.second()*1000);
    int newR = 20+qrand() % 20;    //产生40以内的随机数
    int R = qrand() % 255;    //产生255以内的随机数
    int G = qrand() % 255;    //产生255以内的随机数
    int B = qrand() % 255;    //产生255以内的随机数

    //泡泡信息写入日志文件
    QFile file;
    file.setFileName("C:/Users/Administrator/Desktop/欢欢_彩色泡泡机/泡泡信息.txt");
    QString colorInfo="颜色:RGB:("+QString::number(R)+","+QString::number(G)+","+QString::number(B)+")";
    QString posInfo="坐标:("+QString::number(Pos.x())+QString::number(Pos.y())+")";
    if(file.open(QIODevice::WriteOnly |QIODevice::Text | QIODevice::Append))
    {
        QTextStream stream(&file);
        stream<<colorInfo<<endl;
        stream<<posInfo<<endl;
        stream<<endl;
        file.close();
    }


    Bubble* paopao = new Bubble(newR,Pos.x(),Pos.y());   //动态申请一个泡泡对象
    paopao->move(this->mapToGlobal(Pos));    //将泡泡移动到点击的位置
    //paopao->move(Pos);
    paopao->setColor(QColor(R,G,B));  //RGB数值设置颜色  同样采用随机数机制
    paopao->own_show();   //展示 调用动画
}

三、核心功能具体实现解析

1、如何绘制泡泡?

首先,Qt中有一个绘图事件方法

virtual void QWidget::paintEvent ( QPaintEvent * )

该接口(方法)主要用于各种图形的绘制

a、paintEvent会在何时调用?

paintEvent函数执行:

1、在构建窗体的时候执行

2、在窗体update的时候执行

3、系统认为窗口需要重新绘制的时候执行

b、具体绘制实现

在bubble类中创建成员函数

void paintEvent(QPaintEvent *event);  //绘制事件 泡泡的主要绘制算法实现在此

在源文件bubble.cpp中对其实现进行定义:

//绘制泡泡的图案  画画函数
void Bubble::paintEvent(QPaintEvent *event)   //绘图事件函数 在构造本类对象时自动调用  用于图形的绘制
{
    //画画需要工具(笔和画刷)  笔用于勾勒线条 画刷用于上色   同时还要知道画布是什么
    //QPainter 画笔名(绘图位置)
    QPainter painter(this);   //Qpainter是一个绘图工具 相当于画笔/画刷

    painter.setRenderHint(QPainter::Antialiasing);    //这一句是固定用法 用于图形反走样、抗锯齿   百度查到的

    //void QPainter::setPen ( const QPen & pen )
    //设置新的绘图工具画笔。
    //pen定义了如何绘制线和轮廓,并且它也定义了文本颜色。
    painter.setPen(QPen(m_bubbleColor,10));   //设置画笔  如果是NoPen的话 绘制出来的图案没有边框(界)  勾勒

    //void QPainter::setBrush ( BrushStyle style )
    //设置绘图工具的画刷为黑色和特定的style。
    //painter.setBrush(QBrush(m_bubbleColor));   //设置画刷   为画刷设置颜色  用于给泡泡上色  色彩通过随机的RGB通道值实现

    //联想笔画  写一个字是不是需要笔画和顺序
    //QPainterPath 类(绘图路径)提供了一个容器,用于绘图操作,可以创建和重用图形形状。
    QPainterPath bubblePath;   //泡泡绘制路径
    //path.drawEllipse(x, y, r, r);
    //Ellipse 椭圆(圆)
    bubblePath.addEllipse(QPoint(40, 40), radius, radius);   //将一个圆形添加到绘图路径中
    painter.drawPath(bubblePath);  //绘制图形路径
}
c、绘画工具QPainter
画笔:

QPainter 可以创建画笔 画笔可以设置颜色以及粗细大小等等属性

画笔主要用于勾勒

创建方法:

//QPainter 工具名(画布位置)
QPainter p(this);
painter.setPen(QPen(m_bubbleColor,10));

通过setPen成员函数设置画笔的颜色以及粗细

画刷:

QPainter也可以设置画刷 画刷也有对应的颜色等属性

画刷主要用于图案核心区域的上色

	//void QPainter::setBrush ( BrushStyle style )
    //设置绘图工具的画刷为黑色和特定的style。
    //painter.setBrush(QBrush(Color));   
	
d、绘图路径QPainterPath

QPainterPath相当于我们的笔画

QPainterPath 类(绘图路径)提供了一个容器,用于绘图操作,可以创建和重用图形形状。

path.addEllipse(x,y,r,r) 将一个圆形路径添加到绘图路径中 参数依次为圆心的x,y坐标以及半径

e、下笔draw
painter.drawPath(bubblePath);  //绘制图形路径

让画笔按照规定的路径去进行绘制图形

2、背景图片如何绘制?

也是通过paintEvent进行绘制

具体实现:
void login::paintEvent(QPaintEvent *)
{
    //绘制背景图片
    QPainter p(this);
    p.drawPixmap(0,0,width(),height(),QPixmap(":/files/snow.png"));
    p.end();
}

QPixmap将背景图片读出

3、疑问:Bubble类的本质是什么?

在这里插入图片描述

可以看到Bubble类的本质是一个QWidget,是一个窗体。

而窗体除了其内部图形外还包含窗体边框、窗体标题、以及一些未绘图区域,这就需要我们去进行处理。

4、如何让Bubble窗体只包含泡泡?

通过前面的分析,我们知道Bubble类对象的本质仍是一个窗体,那么我们就需要去除其边框,并让其除泡泡外其余部分均为透明。

未处理前:

在这里插入图片描述

观察Bubble的构造函数:

Bubble::Bubble(int newR,int newX,int newY,QWidget *parent)   //构造函数  构造泡泡图形
    : QWidget(parent)
    , ui(new Ui::Bubble)
    ,x(newX)
    ,y(newY)
    ,radius(newR)
{
    ui->setupUi(this);   //自带的  初始化UI
    //通过调整窗体属性
    //this即当前的对象自身  而当前这个对象本质上是一个widget  是一个页面  通过进行相关参数的调节  将其变为泡泡‘

    //setFixedSize()   设置窗口固定大小
    this->setFixedSize(QSize(80, 80));   //设置固定的大小  泡泡的最大值

    //setWindowFlags   设置窗口属性
    //Qt::FramelessWindowHint无边框化,移动,大小调整
    this->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool);   //设置窗口标志  不带标题栏边框

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

    // 控件显示完关闭后自动删除;
    //this->setAttribute(Qt::WA_DeleteOnClose);  //用于设置各种窗口小部件(widget)的属性。

    //参数解释:动画作用的对象  动画涉及更改的属性  pos:position 位置
    this->BubbleAnimation = new QPropertyAnimation(this, "pos");   //初始化动画成员
}
1、去除窗体边框标题栏

通过设置窗体属性(标志)

this->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool);   //设置窗口标志  不带标题栏边框
2、让窗体大小与泡泡一致
	//setFixedSize()   设置窗口固定大小
    this->setFixedSize(QSize(80, 80));   //设置固定的大小  泡泡的最大值
3、让除泡泡外其余部分透明
	//setAttribute  设置窗体属性  Qt::WA_TranslucentBackground使其透明
    this->setAttribute(Qt::WA_TranslucentBackground);  //使窗体透明

处理后:

在这里插入图片描述

5、如何让泡泡进行漂浮

漂浮的本质是什么:无非就是位置的改变

通过Qt中的属性动画类 QPropertyAnimation //属性动画头文件 property:属性

Qt中的动画类关系如下:

在这里插入图片描述

将其定义在泡泡的展示函数 own_show()里

//自己的show方法
void Bubble::own_show()
{
    QWidget::show();

    QTime time;
    time= QTime::currentTime();
    qsrand(time.msec()+time.second()*1000);
    int v = 2000+qrand() % 3000;    //随机速度
    int exc_x = 200+qrand() % 700;    //随机速度
    int control = qrand() % 2;    //控制模式
    this->BubbleAnimation->setDuration(v);   //设置动画持续时长  参数为一个整形数据   时长随机  时长相当于速度
    this->BubbleAnimation->setStartValue(QPoint(x, y));
    if(control==0)
    {
        qDebug()<<"模式0向上漂浮";
        this->BubbleAnimation->setEndValue(QPoint(x+exc_x, -1000));    //设置结束位置  两点确定一线嘛
    }
    else if(control==1)
    {
        qDebug()<<"模式1向下漂浮";
        this->BubbleAnimation->setEndValue(QPoint(x-exc_x, 2000));    //设置结束位置  两点确定一线嘛
    }
     //设置动画的初始值  由于是一个属性动画 更改的是pos(位置)属性  所以初始值应该是位置(坐标)  QPoint
//    this->BubbleAnimation->setEndValue(QPoint(x+200, -500));    //设置结束位置  两点确定一线嘛
    BubbleAnimation->setEasingCurve(QEasingCurve::InOutQuad);   //这个属性保留了动画的缓和曲线  文档看到的
    this->BubbleAnimation->start();   //动画开始
}
动画的初始化

将初始化放在bubble的构造函数中

this->BubbleAnimation = new QPropertyAnimation(this, "pos");   //初始化动画成员

参数为 动画作用的对象,需要变动的属性

1、设置动画时长
this->BubbleAnimation->setDuration(v);
2、设置开始位置
this->BubbleAnimation->setStartValue(QPoint(x, y));
3、设置结束位置
this->BubbleAnimation->setEndValue(QPoint(x, y));
4、开始动画
this->BubbleAnimation->start();   //动画开始

这个属性保留了动画的缓和曲线 文档看到的
this->BubbleAnimation->start(); //动画开始
}


#### 动画的初始化

将初始化放在bubble的构造函数中

```c++
this->BubbleAnimation = new QPropertyAnimation(this, "pos");   //初始化动画成员

参数为 动画作用的对象,需要变动的属性

1、设置动画时长
this->BubbleAnimation->setDuration(v);
2、设置开始位置
this->BubbleAnimation->setStartValue(QPoint(x, y));
3、设置结束位置
this->BubbleAnimation->setEndValue(QPoint(x, y));
4、开始动画
this->BubbleAnimation->start();   //动画开始
													刘易行  李欢欢
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值