2016-11-07 16 views
0

Hallo Leute, ich brauche Ihre Hilfe,QGraphicsItem Kollision Jitter/zittern

Ich bin eine Zeitleiste wie Widgets in Qt basiert auf dem QGraphics Rahmen zu schaffen. Mein Problem besteht darin, Kollisionen von Objekten (geerbt von QGraphicsRectItem) in meinen Zeitleistenspuren zu behandeln.

Ich verwende die itemChange() -Funktion, um die Kollisionen zu verfolgen. Um die Elemente in der übergeordneten boundingRect halte ich den folgenden Code Wich verwenden wirkt wie ein Zauber

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

Diese Einzelteile sofort stoppt, wenn sie auf den linken oder rechten Rand meiner timline Spuren erreichen, auch wenn ich die Maus außerhalb bewegen meine Sicht/Szene. Es ist wie eine unsichtbare Wand. Jetzt möchte ich das gleiche Verhalten, wenn ein Element in einer Spur mit einer anderen kollidiert.

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

Das Problem ist, dass, wenn ich einen Artikel über Maus gegen ein anderes Element bewegen Sie sie sehen sich schneidende/überlappende und dann den Artikel, den ich zurückschnappt auf das Minimum nicht bewegt Abstand schneidet. Wie schaffe ich es, den bewegenden Gegenstand sofort zu stoppen, wenn er einen anderen Gegenstand berührt (keine zitternde Vor- und Rückwärtsbewegung, die sich kreuzt). Genauso wie die Gegenstände in Elternteilen gehalten werden (erster Codeblock), verhält sich die unsichtbare Wand wie ein Verhalten?

Antwort

0

Ich denke, das Problem ist hier mit "thisRect". Wenn Sie dies von einem ItemPositionChange aus aufrufen, gibt sceneBoundingRect das Begrenzungsrechteck des Elements an seiner vorherigen Position zurück, nicht das neue. Was passiert, ist, dass die aktuelle Position erfolgreich ist, obwohl es eine Kollision gibt, aber die nächste scheitert, weil Sie immer die vorherigen Ergebnisse überprüfen und dann zurückschnappen, um die Kollision zu vermeiden.

Nach dem lokalen Elemente Szene Rechteck bekommen, müssen Sie es an die neue zukünftigen Position des Elements übersetzen:

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

ich die Schaffung von „new_pos“ außerhalb der Schleife verschoben habe, so dass es ist für die Rechteckübersetzung verfügbar. Es ist auch schneller.

+0

Danke für Ihre Antwort, guter Punkt, aber es hat das Problem nicht gelöst. – RobRobRob

+0

Sind irgendwelche dieser Gegenstände parentered? Wenn ja, dann haben Sie eine Mischung von Koordinatensystemen, d. H. "NewPos" und "offset" sind in übergeordneten Koordinaten, aber "thisRect" und "collideRect" sind in Szene Koordinaten. Wenn sie nicht parented sind, dann sind es alle Szenenkoordinaten, und in diesem Fall denke ich, dass das korrekt aussieht. Wenn es sich um übergeordnete Elemente handelt, verwenden Sie mapToScene anstelle von mapToParent und ordnen Sie dann newPos den Szenenkoordinaten für alle Vergleiche und Anpassungen zu und dann zurück zu den übergeordneten Koordinaten, bevor Sie zurückkehren. – goug

+0

Die Elemente werden einem Spurelement zugewiesen, aber sie haben die gleiche Breite wie die Szene und es ist auch rect (0,0). Also sollte der Ursprung x, y derselbe sein. – RobRobRob