2016-11-07 2 views
0

Bonjour les gars j'ai besoin de votre aide,gigue de collision QGraphicsItem/trembler

Je crée une ligne de temps comme widget dans Qt basé sur le cadre QGraphics. Mon problème est de gérer les collisions d'éléments (hérités de QGraphicsRectItem) dans mes pistes Timeline. J'utilise la fonction itemChange() pour suivre les collisions. Pour conserver les éléments dans le boundingRect parent j'utilise le wich code suivant fonctionne comme un charme

if (change == ItemPositionChange && scene()) 
    if (thisRect.intersects(parentRect)) { 
     const QPointF offset(mapFromParent(thisRect.topLeft())); 
     QPointF newPos(value.toPointF()); 

     if (snapToGrid) { 
      newPos.setX(floor(qMin(parentRect.right() - offset.x() - thisRect.width(), 
            qMax(newPos.x(), parentRect.left()/2 - offset.x()))/(snapValue * pxPerSec(duration))) * snapValue * pxPerSec(duration)); 
     } 
     else {    
      newPos.setX(qMin(parentRect.right() - offset.x() - thisRect.width(), 
          qMax(newPos.x(), parentRect.left() - offset.x()))); 
     } 

     newPos.setY(parentItem()->boundingRect().height() * 0.1); 
     return newPos; 
    } 
} 

Cela arrête immédiatement les articles si elles atteignent la limite gauche ou à droite de mes pistes timline, même si je déplace la souris à l'extérieur ma vue/scène. C'est comme un mur invisible. Maintenant, je veux le même comportement si un élément d'une piste entre en collision avec un autre.

const QRectF parentRect(parentItem()->sceneBoundingRect()); 
const QRectF thisRect(sceneBoundingRect()); 

    foreach (QGraphicsItem *qgitem, collidingItems()) { 
     TimelineItem *item = qgraphicsitem_cast<TimelineItem *>(qgitem); 
     QPointF newPos(value.toPointF()); 

     if (item) { 
      const QRectF collideRect = item->sceneBoundingRect(); 
      const QPointF offset(mapFromParent(thisRect.topLeft())); 

      if (thisRect.intersects(collideRect) && thisRect.x() < collideRect.x()) { 
       newPos.setX(collideRect.left() - offset.x() - thisRect.width()); 
      } 

      if (thisRect.intersects(collideRect) && thisRect.x() > collideRect.x()) { 
       newPos.setX(collideRect.right() + offset.x()); 
      } 

     } 

     newPos.setY(parentItem()->boundingRect().height() * 0.1); 
     return newPos; 
    } 

Le problème est que si je me déplace un élément via la souris contre un autre élément que vous voyez intersection/chevauchement, puis l'élément je me suis déplacé en arrière à boutons-pression la distance minimale ne recoupant pas. Comment puis-je arrêter l'objet en mouvement immédiatement s'il en touche un autre (pas de mouvement qui s'entrecroise). Tout comme la façon dont les éléments sont conservés chez les parents boundingRect (premier bloc de code), le mur invisible comme le comportement?

Répondre

0

Je pense que le problème ici est avec "thisRect". Si vous appelez ceci d'un ItemPositionChange, alors sceneBoundingRect renvoie le rectangle de délimitation de l'élément dans sa position précédente, pas le nouveau. Ce qui se passe, c'est que la position actuelle réussit même s'il y a une collision, mais la suivante échoue parce que vous vérifiez toujours les résultats précédents, puis elle revient en arrière pour éviter la collision.

Après avoir obtenu le rectangle de la scène de l'article local, vous aurez besoin de le traduire à la nouvelle position future de l'article:

QPointF new_pos (value.toPointF()); 
QRectF thisRect (sceneBoundingRect()); 
thisRect.translate (new_pos - pos()); 

J'ai déplacé la création de « new_pos » en dehors de la boucle de telle sorte que c'est disponible pour la traduction rectangle. C'est aussi plus rapide.

+0

Merci pour votre réponse, bon point mais cela n'a pas résolu le problème. – RobRobRob

+0

L'un de ces éléments est-il parent? Si tel est le cas, vous disposez d'un mélange de systèmes de coordonnées, c'est-à-dire que "newPos" et "offset" sont dans les coordonnées parentes, mais "thisRect" et "collideRect" sont dans les coordonnées de la scène. Si elles ne sont pas parentales, alors ce sont toutes les coordonnées de la scène, et dans ce cas, je pense que cela semble correct. Si des éléments parents sont concernés, utilisez mapToScene au lieu de mapToParent, puis mappez newPos aux coordonnées de scène pour toutes les comparaisons et ajustements, puis revenez aux coordonnées parent avant de les renvoyer. – goug

+0

Les éléments sont parentés à un élément de piste, mais il a la même largeur que la scène et son rect est également défini sur (0,0). Donc, l'origine x, y devrait être la même. – RobRobRob