2013-08-30 1 views
0

Je crée une animation avec QGraphicsView, QGraphicsScene et QGraphicsItem. Quelqu'un peut-il m'expliquer quand la fonction de peinture est appelée? Bien que je ne change pas les variables de l'article, la fonction de peinture est appelée toutes les ≈100 ms. Puis-je arrêter cela, afin que je puisse repeindre l'objet quand je veux?QGraphicsItem: lorsque la fonction de peinture est appelée

Répondre

1

Vous pouvez définir viewportUpdateMode de QGraphicsView pour modifier la façon dont il est mis à jour. Les options sont les suivantes: -

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

Le Qt docs explains ce que les différentes options font, mais si vous voulez un contrôle total, il suffit de définir à QGraphicsView :: NoViewportUpdate et contrôlez-le vous-même en utilisant un événement QTimer.

2

Vous vous en approchez de la mauvaise façon. L'article ne doit être repeint que lorsque cela est nécessaire - lorsque vous changez son aspect ou son emplacement. C'est quand vous appelez le QGraphicsItem::update(). Le reste sera géré pour vous. Il semble que vous compliquez les choses. Notez que vous devez déterminer le paramètre actuel de l'animation en fonction du temps dans la méthode paint(), ou le "fermer" (par exemple, juste avant l'appel de update()), en utilisant le temps réel! Si vos animations sont dérivées de QAbstractAnimation, c'est déjà fait pour vous. Si ce n'est pas le cas, vous devrez utiliser QElapsedTimer.

La documentation Qt pertinente dit:

Le cadre d'animation appelle updateCurrentTime() quand a changé l'heure actuelle. En réimplémentant cette fonction, vous pouvez suivre la progression de l'animation. Notez que ni l'intervalle entre les appels ni le nombre d'appels à cette fonction ne sont définis; cependant, il sera normalement 60 mises à jour par seconde.

Cela signifie que Qt fera des animations au mieux. Le paramètre currentTime rapporté par l'animation est l'instantané le plus récent au moment où l'animation a été mise à jour dans la boucle d'événements. C'est à peu près ce que tu veux.

La façon la plus simple de traiter tout cela serait d'utiliser QVariantAnimation avec QGraphicsObject. Un exemple est ci-dessous. Au lieu de faire pivoter l'objet, vous pouvez avoir votre propre emplacement et le modifier d'une autre manière. Vous pouvez également, au lieu d'utiliser la connexion de tranche de signal, avoir un QVariantAnimation personnalisé qui prend comme cible votre classe personnalisée QGraphicsItem.

screenshot

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