Qt5开发从入门到精通——第七篇五节( 图形视图—— 图元创建 GraphicsItem V1.2)

欢迎小伙伴的点评✨✨,相互学习、互关必回、全天在线🍳🍳🍳
博主🧑🧑 本着开源的精神交流Qt开发的经验、将持续更新续章,为社区贡献博主自身的开源精神👩‍🚀

前言

本章节会给大家带来基于图元创建 GraphicsItem V1.1开发升级到图元创建 GraphicsItem V1.2开发的解析。

一、 GraphicsItem V1.2升级图元星星移动的功能解析

1.1、增添Startltem类

向项目中添加一个新的 C++类,类名命名为" Startltem",。 Startltem 类继承自 QGraphicsltem 类,实际上是一个图片图元。

1.2、图元框架中星星移动的图元

(1)在 “mainwindow.h” 文件中添加代码如下:

public slots:
void  slotAddAnimationItem();
private:
QAction *addAnimItemAct;

(2)在 “mainwindow.cpp” 文件中添加代码如下:

#include <QGraphicsItemAnimation>
#include <QTimeLine>
#include "startitem.h"

其中,在createActionsO函数中添加代码如下:

    addAnimItemAct = new QAction(tr(" 加入星星"), this);
    connect(addAnimItemAct,SIGNAL(triggered()),this,SLOT(slotAddAnimationItem()));

在 createMenus() 函数中添加代码如下:

itemsMenu->addAction(addAnimItemAct);

在 initScene()函数中添加代码如下:

    for(i=0;i<3;i++)
       slotAddAnimationItem();

函数 slotAddAnimationItem()的具体实现代码如下:

void MainWindow::slotAddAnimationItem()   //在场景中加入一个动画星星
{

    StartItem *item= new StartItem;
    QGraphicsItemAnimation *anim = new QGraphicsItemAnimation;
    anim->setItem(item);
    QTimeLine *timeLine = new QTimeLine(4000);
    timeLine->setCurveShape(QTimeLine::SineCurve);
    timeLine->setLoopCount(0);
    anim->setTimeLine(timeLine);
    int y =(qrand()%400)-200;
    for(int i=0;i<400;i++)
    {
        anim->setPosAt(i/400.0,QPointF(i-200,y));
    }
    timeLine->start();
    scene->addItem(item);

}

二、GraphicsItem V1.2 效果实例

图一
在这里插入图片描述
添加图片到Resources中步骤如下:
图二
在这里插入图片描述

三、原码解析

flashitem.h

#ifndef FLASHLTEM_H
#define FLASHLTEM_H
#include <QGraphicsItem>
#include <QPainter>

class FlashItem : public QObject,public QGraphicsItem
{
    Q_OBJECT
public:
    explicit FlashItem(QObject *parent = nullptr);
    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget);
    void timerEvent(QTimerEvent *);
private:
    bool flash;
    QTimer *timer;
signals:

public slots:
};

#endif // FLASHLTEM_H

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QMenuBar>
#include <QGraphicsEllipseItem>
#include <QDebug>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();

    void initScene();         //初始化场景
    void createActions();     //创建主窗体的所有动作
    void createMenus();       //创建主窗体的菜单栏
public slots:
    void slotNew();           //新建一个显示窗体
    void slotClear ();        //清除场景中所有的图元
    void slotAddEllipseItem();  //在场景中加入一个椭圆形图元
    void slotAddPolygonItem (); //在场景中加入一个多边形图元
    void slotAddTextItem();     //在场景中加入一个文字图元
    void slotAddRectItem ();    //在场景中加入一个长方形图元
    void slotAddAlphaItem();   //在场景中加入一个透明蝴蝶图片


    /*********************/
    void slotAddFlashItem();
    /*********************/

    /*********************/
    void  slotAddAnimationItem();
    /*********************/


private:
    QGraphicsScene *scene;
    QAction *newAct;
    QAction *clearAct;
    QAction *exitAct;
    QAction *addEllipseItemAct;
    QAction *addPolygonItemAct;
    QAction *addTextItemAct;
    QAction *addRectItemAct;
    QAction *addAlphaItemAct;

    /*********************/
    QAction *addFlashItemAct;
    /*********************/

    /*********************/
    QAction *addAnimItemAct;
    /*********************/

};

#endif // MAINWINDOW_H

startitem.h

#ifndef STARTITEM_H
#define STARTITEM_H

#include <QGraphicsItem>
#include <QPainter>
class StartItem : public QGraphicsItem
{
public:
    StartItem();
    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget);
private:
    QPixmap pix;
};

#endif // STARTITEM_H

flashitem.cpp

#include "flashitem.h"

FlashItem::FlashItem(QObject *parent) : QObject(parent)
{
    flash=true;              //为颜色切换标识赋初值
    setFlag(ItemIsMovable);  //设置图元的属性, ItemIsMovable 表示此图元是可移动的,可 用鼠标进行拖曳操作。
    startTimer(1000);        ///启动一个定时器,以 1000 毫秒为时间间隔
}

/*定义图元边界的函数 boundingRect(), 完成以图元坐标系为基础,增加两个像素点的冗余工作。*/
QRectF FlashItem::boundingRect() const
{
    qreal adjust= 2;
    return QRectF(-10-adjust,-10-adjust,43+adjust,43+adjust);
}

/*自定义图元重绘的函数 paint()的具体实现代码如下*/
void FlashItem::paint (QPainter *painter, const QStyleOptionGraphicsItem *option,QWidget *widget)
{
    painter->setPen(Qt::NoPen); //闪烁图元的阴影区不绘制边线
    painter->setBrush (Qt:: darkGray); //闪烁图元的阴影区的阴影画刷颜色为深灰
    painter->drawEllipse(-7,-7,40,40); //绘制阴影区
    painter->setPen(QPen(Qt::black,0));
                                          //闪烁区的椭圆边线颜色为黑色、线宽为 0
    /*设置闪烁区的椭圆画刷颜色根据颜色切换标识 flash 决定在椭圆中填充哪种颜色,颜色在红色和黄色之间选择。*/
    painter->setBrush(flash?(Qt::red):(Qt::yellow));
    /*绘制与阴影区同样形状和大小的椭圆,并错开一定的距离以实现立体的感觉。*/
    painter->drawEllipse( -10,-10,40,40); //(b)
}

/*定时器响应函数 timerEvent()完成颜色切换标识的反置,并在每次反置后调用 update()函数
重绘图元以实现闪烁的效果。*/
void FlashItem::timerEvent(QTimerEvent *)
{
    flash=!flash;
    update();
}

main.cpp

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}

mainwindow.cpp

#include "mainwindow.h"
#include "flashitem.h"
#include <QGraphicsItemAnimation>
#include <QTimeLine>
#include "startitem.h"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
{
     createActions();   //创建主窗体的所有动作
     createMenus();    //创建主窗体的菜单栏
    scene = new QGraphicsScene;
    scene->setSceneRect(-200,-200,400,400);
    initScene (); //初始化场景
    QGraphicsView *view= new QGraphicsView;
    view->setScene(scene);
    view->setMinimumSize(400,400);
    view->show () ;
    setCentralWidget(view);
    resize(550,450);
    setWindowTitle(tr("Graphics Items"));
}

MainWindow::~MainWindow()
{

}

void MainWindow::createActions()   //创建主窗体的所有动作
{
    newAct = new QAction(tr(" 新建 "),this);
    clearAct = new QAction(tr(" 清除") , this) ;
    exitAct = new QAction(tr(" 退出 "),this);
    addEllipseItemAct = new QAction(tr("加入椭圆 "),this);
    addPolygonItemAct = new QAction(tr("加入多边形 "),this);
    addTextItemAct = new QAction(tr("加入文字 "),this);
    addRectItemAct = new QAction(tr("加入长方形 "),this);
    addAlphaItemAct= new QAction(tr("加入透明图片 "),this);
    connect (newAct, SIGNAL (triggered()), this, SLOT (slotNew ()));
    connect(clearAct,SIGNAL (triggered()), this, SLOT (slotClear ()));
    connect (exitAct, SIGNAL (triggered()), this, SLOT (close()));
    connect (addEllipseItemAct,SIGNAL(triggered()), this, SLOT(slotAddEllipseItem ()));
    connect (addPolygonItemAct,SIGNAL(triggered()), this, SLOT(slotAddPolygonItem ())) ;
    connect(addTextItemAct,SIGNAL(triggered()),this,SLOT(slotAddTextItem ())) ;
    connect(addRectItemAct,SIGNAL(triggered()),this,SLOT(slotAddRectItem ()));
    connect(addAlphaItemAct,SIGNAL(triggered()),this,SLOT(slotAddAlphaItem()));

    /*******************************************/
    addFlashItemAct = new QAction(tr("加入闪烁圆 "),this);
    connect(addFlashItemAct,SIGNAL(triggered()),this,SLOT(slotAddFlashItem()));

    addAnimItemAct = new QAction(tr(" 加入星星"), this);
    connect(addAnimItemAct,SIGNAL(triggered()),this,SLOT(slotAddAnimationItem()));

}


void MainWindow::createMenus()    //创建主窗体的菜单栏
{

    QMenu *fileMenu = menuBar () ->addMenu (tr(" 文件")) ;
    fileMenu->addAction(newAct);
    fileMenu->addAction(clearAct);
    fileMenu->addSeparator();
    fileMenu->addAction(exitAct);
    QMenu *itemsMenu = menuBar()->addMenu(tr(" 元素")) ;
    itemsMenu->addAction(addEllipseItemAct);
    itemsMenu->addAction(addPolygonItemAct);
    itemsMenu->addAction(addTextItemAct);
    itemsMenu->addAction(addRectItemAct);
    itemsMenu->addAction(addAlphaItemAct);

    /**********************************/
    itemsMenu->addAction(addFlashItemAct);
    itemsMenu->addAction(addAnimItemAct);

}


void MainWindow:: initScene ()     //初始化场景
{
    int i;
    for(i=0;i<3;i++)
      slotAddEllipseItem ();
    for(i=0;i<3;i++)
      slotAddPolygonItem();
    for(i=0;i<3;i++)
      slotAddTextItem () ;
    for(i=0;i<3;i++)
      slotAddRectItem();
    for(i=0;i<3;i++)
      slotAddAlphaItem();
    for(i=0;i<3;i++)
       slotAddFlashItem();
    for(i=0;i<3;i++)
       slotAddAnimationItem();
}


void MainWindow::slotNew()   //新建一个显示窗体
{
    slotClear();
    initScene();
    MainWindow *newWin = new MainWindow;
    newWin->show ();
}

void MainWindow::slotClear()  //清除场景中所有的图元
{
    QList<QGraphicsItem*>listItem = scene->items();
    while (!listItem.empty())
    {
        scene->removeItem(listItem.at (0));
        listItem.removeAt(0);
    }


}

void MainWindow::slotAddEllipseItem()  //在场景中加入一个椭圆形图元
{
    QGraphicsEllipseItem *item= new QGraphicsEllipseItem(QRectF(0,0,80,60));
    item->setPen (Qt::NoPen);
    item->setBrush(QColor(qrand() %256,qrand() %256,qrand() %256));
    item->setFlag(QGraphicsItem::ItemIsMovable);
    scene->addItem(item);
    item->setPos((qrand() %int (scene->sceneRect () . width())) -200,
    (qrand () %int (scene->sceneRect () . height ())) -200);
}


void MainWindow::slotAddPolygonItem()  //在场景中加入一个多边形图元
{
    QVector<QPoint> v;
    v<<QPoint(30,-15)<<QPoint(0,-30)<<QPoint(-30,-15)
    <<QPoint(-30,15)<<QPoint(0,30)<<QPoint(30,15);
    QGraphicsPolygonItem *item= new QGraphicsPolygonItem(QPolygonF(v));
    item->setBrush (QColor(qrand()%256, qrand () %256, qrand ()%256));
    item->setFlag(QGraphicsItem::ItemIsMovable);
    scene->addItem(item);
    item->setPos((qrand()%int (scene->sceneRect ().width()))-200,
    (qrand() %int (scene->sceneRect().height())) -200);

}

void MainWindow::slotAddTextItem()  //在场景中加入一个文字图元
{
    QFont font("Times",16);
    QGraphicsTextItem *item= new QGraphicsTextItem("Hello Qt");
    item->setFont(font);
    item->setFlag(QGraphicsItem::ItemIsMovable);
    item->setDefaultTextColor(QColor(qrand()%256, qrand()%256, qrand ()%256));
    scene->addItem(item);
    item->setPos((qrand()%int (scene->sceneRect().width())) -200,
    (qrand()%int(scene->sceneRect() .height ()))-200);
}


void MainWindow::slotAddRectItem() //在场景中加入一个长方形图元
{
    QGraphicsRectItem *item= new QGraphicsRectItem(QRectF(0,0, 60,60));
    QPen pen;
    pen.setWidth(3);
    pen. setColor(QColor(qrand()%256, qrand ()%256, qrand()%256));
    item->setPen(pen);
    item->setBrush (QColor (qrand()%256, qrand()%256, qrand()%256));
    item->setFlag(QGraphicsItem::ItemIsMovable);
    scene->addItem(item);
    item->setPos ((qrand()%int (scene->sceneRect ().width())) -200,
    (qrand()%int (scene->sceneRect ().height())) -200);
}

void MainWindow::slotAddAlphaItem() //在场景中加入一个皮卡丘图片
{
    QGraphicsPixmapItem *item=scene->addPixmap(QPixmap(":/src/piKa.png"));
    item->setFlag(QGraphicsItem::ItemIsMovable);
    item->setPos ((qrand ()%int (scene->sceneRect ().width())) -200,
    (qrand() %int (scene->sceneRect () . height())) -200) ;
}


void MainWindow::slotAddFlashItem() //在场景中加入一个闪烁图元
{
    FlashItem *item= new FlashItem;
    scene->addItem (item);
    item->setPos ((qrand()%int (scene->sceneRect () . width())) -200,
    (qrand()%int (scene->sceneRect ().height())) -200);
}

void MainWindow::slotAddAnimationItem()   //在场景中加入一个动画星星
{

    StartItem *item= new StartItem;
    QGraphicsItemAnimation *anim = new QGraphicsItemAnimation;
    anim->setItem(item);
    QTimeLine *timeLine = new QTimeLine(4000);
    timeLine->setCurveShape(QTimeLine::SineCurve);
    timeLine->setLoopCount(0);
    anim->setTimeLine(timeLine);
    int y =(qrand()%400)-200;
    for(int i=0;i<400;i++)
    {
        anim->setPosAt(i/400.0,QPointF(i-200,y));
    }
    timeLine->start();
    scene->addItem(item);

}


startitem.cpp

#include "startitem.h"
/*在 Startltem()构造函数中仅完成读取图片信息的工作。*/
StartItem::StartItem()
{
    pix.load(":/src/star.png");
}
/*定义图元的边界函数 boundingRect(), 它是所有自定义图元均必须实现的函数*/
QRectF StartItem::boundingRect()const
{
  return QRectF (-pix. width() / 2, -pix. height() /2,pix.width () ,pix. height()) ;
}
/*自定义图元重绘函数 paint()*/
void StartItem::paint (QPainter *painter, const QStyleOptionGraphicsItem*option,QWidget *widget)
{
    painter->drawPixmap(boundingRect().topLeft(),pix);
}

四、总结

图元创建会在应用程序开发中经常用到的

非常抱歉,我的回答有误。在Qt 5.9.7中确实没有QGraphicsItemAnimation类,该类在较早版本的Qt中存在,但已在Qt 5.0中被删除。对于Qt 5.9.7及以上版本,可以通过QPropertyAnimation类来实现QGraphicsItem动画效果。 QPropertyAnimation类是一个通用的属性动画类,可以对任何QObject对象的任何属性进行动画操作。对于QGraphicsItem对象,可以通过将其属性(例如位置、旋转角度、缩放比例等)设置为动画属性,来实现动画效果。 以下是使用QPropertyAnimation类实现QGraphicsItem动画的示例代码: ``` QGraphicsItem *item = ...; // 创建要进行动画QGraphicsItem对象 QPropertyAnimation *animation = new QPropertyAnimation(item, "pos"); // 创建QPropertyAnimation对象,指定动画属性为位置属性 animation->setDuration(1000); // 设置动画持续时间为1秒 animation->setStartValue(QPointF(0, 0)); // 设置起点 animation->setEndValue(QPointF(100, 100)); // 设置终点 animation->start(); // 开始动画 ``` 以上代码中,通过创建QPropertyAnimation对象,并将其动画属性设置为QGraphicsItem的位置属性,来实现QGraphicsItem动画效果。动画的起点为(0, 0),终点为(100, 100),持续时间为1秒。最后调用start()方法启动动画。 需要注意的是,QPropertyAnimation类只能对QObject对象的属性进行动画操作,因此对于QGraphicsItem对象来说,需要将其封装为QObject对象,例如通过QGraphicsObject类或自定义QObject子类的方式,从而使其属性可以被QPropertyAnimation对象操作。
评论 35
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

东.'

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

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

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

打赏作者

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

抵扣说明:

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

余额充值