我有一个圆圈,我想在路径上顺利移动。路径类类似于从QPainterPath派生的水平U.当我启动计时器(QTimeLine对象)时,圆圈只是从路径的开始跳到结束(上部U叉的开始到下部叉的末端),没有平滑的动画。不幸的是,QTimeLine :: setLoopCount(int n)也不起作用。
你对这个原因有什么看法吗?
// 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();
答案 0 :(得分:2)
不推荐使用QGraphicsAnimation
类。你想要的是QPainterPath
和动画系统之间的适配器。请参阅下面的完整示例。
使用画家路径制作动画需要一些额外的平滑(重新取样),因为路径上会有速度变化,看起来并不那么好。运行下面的代码时,您可能会注意到它。画家路径用于绘画,而不是用于制作动画。
这种不当行为的程度将取决于您使用的路径类型,因此最终可能会对您所使用的特定用例工作正常。
#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"