我正在使用QGraphicsView,QGraphicsScene和QGraphicsItem创建动画。有人在调用绘画功能时能解释一下吗?虽然我没有更改项目的变量,但每隔≈100ms调用一次paint函数。我可以阻止它,所以我可以在需要时重新绘制该项目吗?
答案 0 :(得分:2)
你正以错误的方式接近它。该项目应仅在需要时重新绘制 - 当您更改其外观或位置时。那是你打电话给QGraphicsItem::update()
的时候。其余的将为您处理。看来你的事情太复杂了。
请注意,您需要在paint()
方法中确定动画的当前时间相关参数,或者“关闭”它(例如,在调用update()
之前),使用实际时间!如果您的动画来自QAbstractAnimation
,那么它已经为您完成了。如果不是,那么您必须自己使用QElapsedTimer
。
相关的Qt文档说:
当前时间发生变化时,动画框架会调用
updateCurrentTime()
。通过重新实现此功能,您可以跟踪动画进度。注意,调用之间的间隔和对此函数的调用次数都没有定义;但是,它通常每秒更新60次。
这意味着Qt将尽最大努力进行动画制作。动画报告的currentTime是动画在事件循环中更新时的最新时间快照。这几乎就是你想要的。
处理所有这些问题的最简单方法是将QVariantAnimation
与QGraphicsObject
一起使用。一个例子如下。您可以拥有自己的插槽,而不是旋转对象,然后以其他方式对其进行修改。您也可以使用定制的QVariantAnimation
代替使用信号槽连接,将自定义QGraphicsItem
派生类作为目标。
main.cpp
#include <QApplication>
#include <QGraphicsScene>
#include <QGraphicsView>
#include <QGraphicsObject>
#include <QPropertyAnimation>
#include <QGraphicsRectItem>
class EmptyGraphicsObject : public QGraphicsObject
{
public:
EmptyGraphicsObject() {}
QRectF boundingRect() const { return QRectF(0, 0, 0, 0); }
void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) {}
};
class View : public QGraphicsView
{
public:
View(QGraphicsScene *scene, QWidget *parent = 0) : QGraphicsView(scene, parent) {
setRenderHint(QPainter::Antialiasing);
}
void resizeEvent(QResizeEvent *) {
fitInView(-2, -2, 4, 4, Qt::KeepAspectRatio);
}
};
void setupScene(QGraphicsScene &s)
{
QGraphicsObject * obj = new EmptyGraphicsObject;
QGraphicsRectItem * rect = new QGraphicsRectItem(-1, 0.3, 2, 0.3, obj);
QPropertyAnimation * anim = new QPropertyAnimation(obj, "rotation", &s);
s.addItem(obj);
rect->setPen(QPen(Qt::darkBlue, 0.1));
anim->setDuration(2000);
anim->setStartValue(0);
anim->setEndValue(360);
anim->setEasingCurve(QEasingCurve::InBounce);
anim->setLoopCount(-1);
anim->start();
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsScene s;
setupScene(s);
View v(&s);
v.show();
return a.exec();
}
答案 1 :(得分:1)
您可以设置QGraphicsView的viewportUpdateMode以更改其更新方式。选项包括: -
Qt docs explains不同选项的作用,但如果你想要完全控制,只需设置为QGraphicsView :: NoViewportUpdate并使用QTimer事件自行控制它。