Qt浅谈之十七:飞舞的蝴蝶(GraphicsView框架)

一、简介

       GraphicsView框架结构主要包含三个主要的类QGraphicsScene(容器)、QGraphicsView(视图)、QGraphicsItem(图形项)。QGraphicsScene本身不可见必须通过与之相连的QGraphicsView视口类来显示及与外界进行互操作,主要提供项目的操作接口、传递事件和管理各个项目状态;QGraphicsView提供一个可视的窗口,用于显示场景中的项目,一个场景中可以有多个视口;QGraphicsItem是场景中各个项目的基础类。

二、关系图

(1)三者间的关系


(2)坐标系统

QGraphicsScene坐标系是以中心为原点(0,0),QGraphicsView继承自QWidget以窗口的左上角作为自己坐标系的原点,而QGraphicsItem则有自己的坐标系其paint()函数重画时以此坐标系为基准。

(3)坐标映射

三个坐标系之间的相互转换函数及图形项与图形项之间的转换函数。

三、详解

1、运行图


2、解析

(1)利用定时器实现QGraphicsItem不停上下飞舞的蝴蝶的动画效果

#include <QGraphicsItem>
#include <QObject>

class Butterfly : public QObject, public QGraphicsItem
{
    Q_OBJECT
public:
    Butterfly();
    void timerEvent(QTimerEvent *);
    QRectF boundingRect() const;
   
protected:
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

    
private:
    bool up;
    QPixmap pix_up;
    QPixmap pix_down; 
    
    qreal angle;

};
static const double PI = 3.14159265358979323846264338327950288419717;

Butterfly::Butterfly()
{ 
    setFlag(QGraphicsItem::ItemIsMovable);

    pix_up.load(":/images/butterfly1.PNG");
    pix_down.load(":/images/butterfly2.PNG");
    up = true;
    startTimer(100);
}

QRectF Butterfly::boundingRect() const
{
    qreal adjust = 8;
    return QRectF(-pix_up.width()/2-adjust,-pix_up.height()/2-adjust,
                pix_up.width()+adjust*2,pix_up.height()+2*adjust);
}

void Butterfly::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    if(up)
    {
    	painter->drawPixmap(boundingRect().topLeft(),pix_up);
    	up = !up;
    }
    else
    {
    	painter->drawPixmap(boundingRect().topLeft(),pix_down);
    	up = !up;
    }
//    painter->setPen(Qt::NoPen);
//    painter->setBrush(Qt::darkGray);
//    painter->drawEllipse(-7,-7,40,40);

//    painter->setPen(QPen(Qt::black,0));
//    painter->setBrush(flash ? (Qt::red):(Qt::yellow));
//    painter->drawEllipse(-10,-10,40,40);
    	
}

void Butterfly::timerEvent(QTimerEvent *)
{
    // edge controll
    qreal edgex = scene()->sceneRect().right()+boundingRect().width()/2;
    qreal edgetop = scene()->sceneRect().top()+boundingRect().height()/2;
    qreal edgebottom = scene()->sceneRect().bottom()+boundingRect().height()/2;
    //qDebug() << scene()->itemsBoundingRect();
    if (pos().x() >= edgex)
    	setPos(scene()->sceneRect().left(),pos().y());
    if (pos().y() <= edgetop)
        setPos(pos().x(),scene()->sceneRect().bottom());
    if (pos().y() >= edgebottom)
        setPos(pos().x(),scene()->sceneRect().top());
    
    angle += (qrand()%10)/20.0;
    qreal dx = fabs(sin(angle*PI)*10.0);
    qreal dy = (qrand()%20)-10.0;
    
    setPos(mapToParent(dx,dy));
    update();
}
分析:在定时器的timeEvent()中对QGraphicsItem进行重画,重画paint()函数中飞舞的蝴蝶是由两幅图片组成,蝴蝶的移动边界做一个限定,dx和dy是相对于蝴蝶的坐标系而言的,调用setPos函数时使用mapToParent()函数映射成场景的坐标。setFlag(QGraphicsItem::ItemIsMovable);使蝴蝶可以通过鼠标移动。

(2)来回移动的星星

class StarItem : public QGraphicsItem
{
public:
    StarItem();

    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);

private:
    QPixmap pix;
};
StarItem::StarItem()
{
    pix.load(":/images/star.png");
}

QRectF StarItem::boundingRect() const
{
    return QRectF(-pix.width()/2,-pix.height()/2,pix.width(),pix.height());
}

void
StarItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
    painter->drawPixmap(boundingRect().topLeft(),pix);
}
{
    StarItem *star = new StarItem;
    QGraphicsItemAnimation *anim = new QGraphicsItemAnimation;
    anim->setItem(star);
    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(star);
}
分析:利用QGraphicsItemAnimation类和QTimeLine实现项目的动画效果(也可使用定时器QTimer结合重绘函数来实现)。

(3)简单正方形

{
    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);
    item->setPos(-200, -200);
} 
分析:利用继承QGraphicsItem的类QGraphicsRectItem添加一个正方形的图形项。

四、总结

(1)GraphicsView框架相对与QWidget难于理解,且内容也比较多,以后会继续更新相应的内容。

(2)本文没有涉及GraphicsView的事件的处理和传播(事件首先由视图接收然后传递给场景再由场景给相应的图形项),读者可自行查阅相应的资料。

(3)源码已经打包上传到csdn上可登录下载(http://download.csdn.net/detail/taiyang1987912/7785071)。  

(4)本人思路有限,若有更好的设计建议,也可发邮件沟通,在此先感谢!邮箱地址yang.ao@i-soft.com.cn。


  • 10
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
以下是关于Qt Graphics View的教程: 1. 官方文档:Qt Graphics View官方文档是使用该框架的最佳参考资料,其中详细介绍了该框架的所有功能和API。 2. 基本概念:在学习Qt Graphics View之前,需要先了解一些基本概念,如场景(Scene)、视图(View)、图元(Item)等。 3. 创建场景和视图:使用Qt Graphics View创建场景和视图非常简单。可以通过代码或Qt Designer创建一个新的Graphics View窗口。首先需要创建场景,然后将场景与视图关联。 4. 添加图元:可以使用Qt Graphics View中的图元(Item)来绘制2D图形。可以添加图元到场景中,然后它们就会显示在视图中。Qt Graphics View提供了一些内置的图元类,如矩形、椭圆、文字、线条等。 5. 图元转换和变换:使用Qt Graphics View可以对图元进行多种转换和变换操作,如平移、缩放、旋转、剪切、选择等。这些操作可以通过使用QTransform类来实现。 6. 事件处理和信号机制:Qt Graphics View提供了丰富的事件和信号机制,方便用户进行图形交互和动画效果的实现。可以通过重载事件处理函数和连接信号和槽函数来处理这些事件和信号。 7. 动画效果:使用Qt Graphics View可以实现各种动画效果,如平移、旋转、缩放等。可以使用QPropertyAnimation类来实现这些效果。 8. 场景和视图的组合:使用Qt Graphics View可以将多个场景和视图组合在一起,创建复杂的图形场景。可以使用QGraphicsProxyWidget类将QWidget转换为图元,然后将它们添加到场景中。 希望以上教程能帮助你了解Qt Graphics View

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

乌托邦2号

博文不易,支持的请给予小小打赏

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

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

打赏作者

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

抵扣说明:

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

余额充值