Qt学习之Graphics View框架(实现开机动画)

目录

一、实现效果

二、图元、视图、场景简单介绍

1、相互关系

2、头文件

         3、实现流程

三、代码实现

1、自定义一个Item(图元)

1.1  新建一个类myItem继承于QGraphicsItem

1.2  myItem头文件(.h)

1.3  重载构造函数

1.4  boundingRect函数以及paint函数实现

1.5  advance函数实现

1.6  完整代码(.cpp)

2、自定义一个view(视图)

2.1  新建一个类WelcomeWin继承于QGraphicsView

2.2  WelcomeWin头文件(.h)

2.3  WelcomeWin完整代码(.cpp)

四、主函数测试


一、实现效果

        图元碰撞,提示开机成功。

二、图元、视图、场景简单介绍

1、相互关系

图元:包含在场景中,一个场景可以有多个图元。

视图:相当于一个小窗口,用来观察场景的,视图可以有多个场景。

场景:相当于一块幕布,里面有好多元素(图元)。

2、头文件

#include <QGraphicsItem>   //图元

#include <QGraphicsView>   //视图

#include <QGraphicsScene>  //场景

3、实现流程

大致流程是:新建图元——>新建场景——>场景添加图元——>新建视图——>视图关联场景。

三、代码实现

1、自定义一个Item(图元)

1.1  新建一个类myItem继承于QGraphicsItem

        记得勾上QObject,因为之后会用到信号与槽。

1.2  myItem头文件(.h)

        自定义Item类主要重写了boundingRect函数、paint函数以及advance函数。boundingRect用于返回一个碰撞大小的矩形框,对之后碰撞检测有影响。paint函数主要用于图元的绘制,实现自定义图元。advance函数用于图元移动。

        以及自定义了一个信号(signals):void MyItemcolliding(),主要用于两个图元碰撞到了之后发射该信号,然后图元消失,成功开机。

        因为用到信号,所以要添加Q_OBJECT宏,并继承与QObject,不然后期可能会出现报错。

#ifndef MYITEM_H
#define MYITEM_H

#include <QObject>
#include <QString>
#include <QGraphicsItem>

class myItem : public QObject, public QGraphicsItem
{
    Q_OBJECT
public:
    myItem();
    myItem(int x,int y,QString file,int pos);
    QRectF boundingRect() const override;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;

private:
    int x,y,w,h,role;
    QString file;

public slots:
    void advance(int phase) override;

signals:
    void MyItemcolliding();
};

#endif // MYITEM_H

1.3  重载构造函数

int  x、int  y:        图元的位置(坐标)

QString file:       图元所要加载的图片所在的路径

int role:        图元的类型,本例主要用于定义警察和小偷

myItem::myItem(int x, int y, QString file, int role)
{
    this->x=x;
    this->y=y;
    this->role=role;
    this->file=file;
    this->w=QImage(this->file).width();
    this->h=QImage(this->file).height();
    this->setPos(this->x,this->y);
}

1.4  boundingRect函数以及paint函数实现

        collidingItems()会返回一个碰撞图元链表,也就是说里面存放的是正在发生碰撞的图元,可以用 isEmpty()函数来判断是否图元发生了碰撞。isEmpty()函数返回值为bool类型,为空返回true,否则返回false。

QRectF myItem::boundingRect() const
{
    //qreal penWidth = 1; //不定义画笔宽度了,直接用0取代

    return QRectF(0, 0, this->w, this->h);//返回碰撞的矩形框
}


void myItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    //标明该参数没有使用
    Q_UNUSED(option)
    Q_UNUSED(widget)

    if(collidingItems().isEmpty())//没有与其他图形项碰撞
    {
        //没有碰撞就绘图,碰撞到了图元消失(不绘制)
        painter->drawImage(QRectF(0,0,this->w,this->h),QImage(this->file));
    }

    //可以加个else,图元碰撞到了变成其他图片
}

1.5  advance函数实现

        如果collidingItems()不为空,则碰撞到了,就发送自定义信号。

void myItem::advance(int phase)
{
    //如果phase为0,表示将开始移动则返回
    if(!phase)
    {
        return;
    }
    if(!collidingItems().isEmpty())
    {
        emit MyItemcolliding();//碰撞后发射信号
    }
    if(this->role == 1)//警察,移动快
    {
        moveBy(-5,0);//向左移动5
    }
    else if(this->role == -1)//小偷,移动慢
    {
        moveBy(-2,0);//向左移动2
    }

}

1.6  完整代码(.cpp)

#include "myitem.h"
#include <QPainter>

myItem::myItem()
{

}

myItem::myItem(int x, int y, QString file, int role)
{
    this->x=x;
    this->y=y;
    this->role=role;
    this->file=file;
    this->w=QImage(this->file).width();
    this->h=QImage(this->file).height();
    this->setPos(this->x,this->y);
}

QRectF myItem::boundingRect() const
{
    //qreal penWidth = 1; //不定义画笔宽度了,直接用0取代
    return QRectF(0, 0, this->w, this->h);
}

void myItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    //标明该参数没有使用
    Q_UNUSED(option)
    Q_UNUSED(widget)

    if(collidingItems().isEmpty())//没有与其他图形项碰撞
    {
        //没有碰撞就绘图,碰撞到了图元消失(不绘制)
        painter->drawImage(QRectF(0,0,this->w,this->h),QImage(this->file));
    }
    //可以加个else,图元碰撞到了变成其他图片
}

void myItem::advance(int phase)
{
    //如果phase为0,表示将开始移动则返回
    if(!phase)
    {
        return;
    }
    if(!collidingItems().isEmpty())
    {
        emit MyItemcolliding();//碰撞后发射信号
    }
    if(this->role == 1)//警察,移动快
    {
        moveBy(-5,0);//向左移动5
    }
    else if(this->role == -1)//小偷,移动慢
    {
        moveBy(-2,0);//向左移动2
    }

}

2、自定义一个view(视图)

2.1  新建一个类WelcomeWin继承于QGraphicsView

        记得勾上QObject。

2.2  WelcomeWin头文件(.h)

        包括两个自定义图元,一个定时器,一个场景,以及一个槽函数。也要加上Q_OBJECT宏。

#ifndef WELCOMEWIN_H
#define WELCOMEWIN_H

#include <QObject>
#include <QGraphicsView>
#include <QGraphicsScene>
#include <QTimer>
#include "myitem.h"

class WelcomeWin : public QGraphicsView
{
    Q_OBJECT
public:
    WelcomeWin();

private:
    myItem *item1, *item2; //添加两个自定义Item
    
    QTimer *timer;  //定时器,用于图元移动
    
    QGraphicsScene *sence;  //场景

public slots:
    void timerStop(); //槽函数,用于关闭定时器,提示开机成功
};

#endif // WELCOMEWIN_H

2.3  WelcomeWin完整代码(.cpp)

#include "welcomewin.h"
#include <QMessageBox>

WelcomeWin::WelcomeWin()
{
    timer=new QTimer;
    //新建图元
    item1=new myItem(this->width()-240,450,"image/thrief.png",-1);//-1代表小偷
    item2=new myItem(this->width()+100,450,"image/police.png",1);//1代表警察

    //新建场景
    sence=new QGraphicsScene;
    sence->setSceneRect(0,0,this->width()+459,this->height()+368);//设置场景位置,可根据自己的背景图调位置

    //场景添加图元
    sence->addItem(item1);
    sence->addItem(item2);

    //视图关联场景
    this->setScene(sence);
    this->setFixedSize(800,550);
    
    this->setWindowTitle("Welcome");
    this->setBackgroundBrush(QBrush(QPixmap("image/start-background.jpeg")));//设置视图背景
    this->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);//不要水平滑动条
    this->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);//不要垂直滑动条

    this->setWindowFlags(Qt::FramelessWindowHint);//设置窗体无边框
    this->setWindowIcon(QIcon("image/警徽.png"));

    //定时器
    connect(timer,SIGNAL(timeout()),sence,SLOT(advance()));//定时器超时会调用图元的advance函数,图元移动
    timer->start(30);//每30毫秒超时

    connect(item2,SIGNAL(MyItemcolliding()),this,SLOT(timerStop()));//图元碰撞会发送MyItemcolliding()信号,并关联槽
}

//槽函数实现
void WelcomeWin::timerStop()
{
    this->timer->stop(); //定时器关闭

    QMessageBox msgBox(this);  //消息提示框

    msgBox.setWindowIcon(QIcon("image/提示.png"));
    msgBox.setWindowTitle("Tip");
    msgBox.setStyleSheet("QMessageBox QLabel{min-width: 400px;"
                         " min-height: 100px;font:16pt; font-family:'楷体';}");

    msgBox.setText("开机成功");
    msgBox.exec();
    this->close();  //开机成功,当前窗口关闭
}

四、主函数测试

        测试结果在文章开头。

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);

    WelcomeWin w;
    
    w.show();

    return a.exec();
}

原创不易,转载请标明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

似末

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值