图形项目通过QGraphicsItemAnimation跳到路径的结尾不动, [英] Graphic item jumps to the end of path via QGraphicsItemAnimation without moving

查看:263
本文介绍了图形项目通过QGraphicsItemAnimation跳到路径的结尾不动,的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有我想要的道路上顺利地移动了一圈。 Path类是想从QPainterPath派生的水平的U。当我启动定时器(QTimeLine对象)的圆圈刚刚从路径的起点到终点(上û叉子叉较低的末尾开始),没有流畅的动画跳跃。不幸的是,QTimeLine :: setLoopCount(INT N)不工作过。

你有关于任何理由想法?

  // UPATH(INT forkLen,诠释forksDistance,QPointF的startPoint)
UPATH * UPATH =新UPATH(500,60,QPointF(10,10));的QList< QPointF>分= uPath-> pathPoints(0.006); //返回路径的分
                                                  //通过QPainterPath :: pointAtPercent实现()的QGraphicsItem *球=新QGraphicsEllipseItem(0,0,10,10);QTimeLine *定时器=新QTimeLine(5000);
timer-> setFrameRange(0,100);
timer-> setLoopCount(2); //不起作用QGraphicsItemAnimation *动画=新QGraphicsItemAnimation;
animation-> setItem(球);
animation-> setTimeLine(定时器);的for(int i = 0; I< points.count(); ++ I)
    animation-> setPosAt(I / points.count(),points.at(ⅰ));QGraphicsScene *场景=新QGraphicsScene();
scene->的addItem(球);*的QGraphicsView鉴于=新的QGraphicsView(场景);
取景> setRenderHint(QPainter的抗锯齿::);
视图 - >显示();timer->启动();


解决方案

QGraphicsAnimation 类去precated。你想要的是一个 QPainterPath 和动画系统之间的适配器。请参阅下面的完整的例子。

使用画家路径,动画需要一些额外的滤波(采样),因为将沿着路径速度的变化,它会不看所有的伟大。当您运行下面的code您可能会注意到它。画家路径意味着绘画,而不是动画的东西。

这不端行为的程度将取决于那种你正在使用的道路,所以它最终可能会为你有特定用例的工作确定。

 的#include<&的QApplication GT;
#包括LT&;&QAbstractAnimation GT;
#包括LT&;&QPainterPath GT;
#包括LT&; QGraphicsScene>
#包括LT&;&的QGraphicsView GT;
#包括LT&;&QGraphicsEllipseItem GT;
#包括LT&;&QDebug GT;类PathAnimation:公共QAbstractAnimation {
    Q_OBJECT
    Q_PROPERTY(INT持续时间READ WRITE setDuration)
    QPainterPath m_path;
    INT m_duration;
    QVector< QPointF> m_cache;
    *的QGraphicsItem m_target;
    INT m_hits,m_misses;
上市:
    PathAnimation(常量QPainterPath&放大器;路径,QObject的*父= 0):
        QAbstractAnimation(父),m_path(路径),m_duration(1000),m_cache(m_duration),m_target(0),m_hits(0),m_misses(0){}
    〜PathAnimation(){qDebug()&所述;&下; m_hits<< m_misses; }
    INT持续时间()const的{返回m_duration; }
    无效setDuration(INT持续时间){
        如果(时间== 0 ||时间== m_duration)回报;
        m_duration =持续时间;
        m_cache.clear();
        m_cache.resize(m_duration);
    }
    无效setTarget(*的QGraphicsItem目标){
        m_target =目标;
    }
    无效updateCurrentTime(INT MS){
        QPointF点= m_cache.at(毫秒);
        如果(!point.isNull()){
            ++ m_hits;
        }其他{
            点= m_path.pointAtPercent(QREAL(MS)/ m_duration);
            m_cache [毫秒] =点;
            ++ m_misses;
        }
        如果(m_target)m_target-> setPos(点);
    }
};INT主(INT ARGC,CHAR *的argv [])
{
    QApplication的一个(ARGC,ARGV);
    QGraphicsEllipseItem *项=新QGraphicsEllipseItem(-5,-5,10,10);
    本期特价货品> setPen(QPen(Qt的::红色,2));
    本期特价货品> setBrush(QT ::浅灰色);    QPainterPath路径;
    path.addEllipse(0,0,100,100);
    PathAnimation动画(路径);
    animation.setTarget(项目);    QGraphicsScene现场;
    scene.addItem(项目);
    观点的QGraphicsView(安培;场景);
    view.setSceneRect(-50,-50,200,200);    animation.setLoopCount(-1);
    animation.start();
    view.show();    返回a.exec();
}#包括main.moc

I have a circle which I want to move smoothly on a path. The path class is like a horizontal U derived from the QPainterPath. when I start timer (QTimeLine object) the circle just jumps from the start of path to the end (start of upper U fork to the end of lower fork) with no smooth animation. Unfortunately, the QTimeLine::setLoopCount(int n) doesn't work too.

Do you have any idea about the reason?

// UPath(int forkLen, int forksDistance, QPointF startPoint)
UPath* uPath = new UPath(500, 60, QPointF(10, 10));

QList<QPointF> points = uPath->pathPoints(0.006); // returns the points of the path
                                                  // implemented by QPainterPath::pointAtPercent()

QGraphicsItem *ball = new QGraphicsEllipseItem(0, 0, 10, 10);

QTimeLine *timer = new QTimeLine(5000);
timer->setFrameRange(0, 100);
timer->setLoopCount(2);    // doesn't work

QGraphicsItemAnimation *animation = new QGraphicsItemAnimation;
animation->setItem(ball);
animation->setTimeLine(timer);

for (int i = 0; i < points.count(); ++i)
    animation->setPosAt(i/points.count(), points.at(i));

QGraphicsScene *scene = new QGraphicsScene();
scene->addItem(ball);

QGraphicsView *view = new QGraphicsView(scene);
view->setRenderHint(QPainter::Antialiasing);
view->show();

timer->start();

解决方案

The QGraphicsAnimation class is deprecated. What you want is an adapter between a QPainterPath and the animation system. See below for a complete example.

Using painter paths for animations requires some extra smoothing (resampling) as there will be velocity changes along the path, and it won't look all that great. You may notice it when you run the code below. Painter paths are meant for painting, not for animating stuff.

The extent of this misbehavior will depend on the kind of path you're using, so it may end up working OK for the particular use case you have.

#include <QApplication>
#include <QAbstractAnimation>
#include <QPainterPath>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsEllipseItem>
#include <QDebug>

class PathAnimation : public QAbstractAnimation {
    Q_OBJECT
    Q_PROPERTY(int duration READ duration WRITE setDuration)
    QPainterPath m_path;
    int m_duration;
    QVector<QPointF> m_cache;
    QGraphicsItem * m_target;
    int m_hits, m_misses;
public:
    PathAnimation(const QPainterPath & path, QObject * parent = 0) :
        QAbstractAnimation(parent), m_path(path), m_duration(1000), m_cache(m_duration), m_target(0), m_hits(0), m_misses(0) {}
    ~PathAnimation() { qDebug() << m_hits << m_misses; }
    int duration() const { return m_duration; }
    void setDuration(int duration) {
        if (duration == 0 || duration == m_duration) return;
        m_duration = duration;
        m_cache.clear();
        m_cache.resize(m_duration);
    }
    void setTarget(QGraphicsItem * target) {
        m_target = target;
    }
    void updateCurrentTime(int ms) {
        QPointF point = m_cache.at(ms);
        if (! point.isNull()) {
            ++ m_hits;
        } else {
            point = m_path.pointAtPercent(qreal(ms) / m_duration);
            m_cache[ms] = point;
            ++ m_misses;
        }
        if (m_target) m_target->setPos(point);
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QGraphicsEllipseItem * item = new QGraphicsEllipseItem(-5, -5, 10, 10);
    item->setPen(QPen(Qt::red, 2));
    item->setBrush(Qt::lightGray);

    QPainterPath path;
    path.addEllipse(0, 0, 100, 100);
    PathAnimation animation(path);
    animation.setTarget(item);

    QGraphicsScene scene;
    scene.addItem(item);
    QGraphicsView view(&scene);
    view.setSceneRect(-50, -50, 200, 200);

    animation.setLoopCount(-1);
    animation.start();
    view.show();

    return a.exec();
}

#include "main.moc"

这篇关于图形项目通过QGraphicsItemAnimation跳到路径的结尾不动,的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆