0

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();
4

1 回答 1

2

该类QGraphicsAnimation已弃用。您需要的是 aQPainterPath和动画系统之间的适配器。请参阅下面的完整示例。

为动画使用画家路径需要一些额外的平滑(重新采样),因为沿着路径会有速度变化,而且看起来不会那么好。当您运行下面的代码时,您可能会注意到它。画家路径是用来绘画的,而不是用来制作动画的。

这种不当行为的程度将取决于您使用的路径类型,因此对于您拥有的特定用例,它可能最终可以正常工作。

#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"
于 2013-09-09T13:35:15.483 回答