QGraphicsItem: when paint function is called

≯℡__Kan透↙ 提交于 2019-12-02 14:23:18

问题


I am creating an animation with QGraphicsView, QGraphicsScene and QGraphicsItem. Can someone explain me when the paint function is called? Although I does not change variables of the item, the paint function is called every ≈100 ms. Can I stop that, so i can repaint the item when I want?


回答1:


You are approaching it the wrong way. The item should be repainted only when needed - when you change how it looks or where it's located. That's when you call the QGraphicsItem::update(). The rest will be handled for you. It seems you're overcomplicating things.

Do note that you need to be determining the current time-dependent parameter of the animation within the paint() method, or "close" to it (say, right before update() is called), using actual time! If your animations are derived from QAbstractAnimation, it's already done for you. If they are not, then you'll have to use QElapsedTimer yourself.

The relevant Qt documentation says:

The animation framework calls updateCurrentTime() when current time has changed. By reimplementing this function, you can track the animation progress. Note that neither the interval between calls nor the number of calls to this function are defined; though, it will normally be 60 updates per second.

This means that Qt will do animations on a best-effort basis. The currentTime reported by the animation is the most recent time snapshot at the moment the animation was updated in the event loop. This is pretty much what you want.

The simplest way to deal with all this would be to use QVariantAnimation with QGraphicsObject. An example is below. Instead of rotating the object, you may have your own slot and modify it in some other way. You can also, instead of using signal-slot connection, have a customized QVariantAnimation that takes your custom QGraphicsItem-derived class as a target.

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



回答2:


You can set the viewportUpdateMode of the QGraphicsView to change how it updates. The options are: -

  • QGraphicsView::FullViewportUpdate
  • QGraphicsView::MinimalViewportUpdate
  • QGraphicsView::SmartViewportUpdate
  • QGraphicsView::BoundingRectViewportUpdate
  • QGraphicsView::NoViewportUpdate

The Qt docs explains what the different options do, but if you want full control, just set to QGraphicsView::NoViewportUpdate and control it yourself using a QTimer event.



来源:https://stackoverflow.com/questions/18528959/qgraphicsitem-when-paint-function-is-called

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!