2016-11-07 20 views
0

こんにちはみんな、QGraphicsItem衝突ジッタ/私はあなたの助けが必要

私はQGraphicsフレームワークに基づくのQtでウィジェットのようにタイムラインを作成していますが震えます。私の問題は、タイムラインのトラックで(QGraphicsRectItemから継承された)アイテムの衝突を処理することです。

itemChange()関数を使用して、衝突を追跡します。私は次のコードウィッヒを使用し、親boundingRectにアイテムを保持するためには、彼らは私のtimlineトラックの左または右の境界に達した場合、これは私が外にマウスを移動した場合でも、すぐにアイテムを停止し、魅力

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

のように動作します私のビュー/シーン。それは目に見えない壁のようです。 トラック内のあるアイテムが別のアイテムと衝突する場合、同じ動作が必要になります。

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

問題は、私は別の項目に対するマウス経由でアイテムを移動する場合は、それらが重複/交差し、その後、私は戻っ最小限にスナップを移動した項目は距離を交差していない参照のことです。移動するアイテムが他のアイテムに当たった場合、直ちに停止する方法を教えてください(震えや背中の動きが交差しないもの)。アイテムが親のboundingRect(最初のコードブロック)に保持されているように、目に見えない壁はビヘイビアのように見えますか?

答えて

0

ここでの問題は「thisRect」だと思います。これをItemPositionChangeから呼び出す場合、sceneBoundingRectはアイテムの境界矩形を新しい位置ではなく前の位置に返します。何が起こるかは、現在の位置は衝突があっても成功するが、前の結果を常にチェックしているので、次の衝突は失敗し、衝突を避けるためにスナップバックするためです。

ローカルアイテムのシーン矩形を取得した後、アイテムの新しい未来位置にそれを翻訳する必要があります:

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

ように、私はループの外で「new_pos」の作成を移動しましたそれは矩形の翻訳に利用できます。それも速いです。

+0

ご回答いただきありがとうございますが、問題は解決しませんでした。 – RobRobRob

+0

これらのアイテムのいずれにも親がありますか?その場合、座標系が混在しています。つまり、「newPos」と「offset」は親座標にありますが、「thisRect」と「collideRect」はシーン座標にあります。それらがペアレント化されていない場合、それはすべてのシーン座標です。この場合、これは正しいと思います。親アイテムが含まれている場合は、mapToParentの代わりにmapToSceneを使用し、newPosをシーン座標にマップしてすべての比較および調整を行い、親座標に戻ってから戻します。 – goug

+0

アイテムはトラックアイテムのペアレントですが、シーンと同じ幅を持ち、rectも(0,0)に設定されています。したがって、x、yの原点は同じでなければなりません。 – RobRobRob

関連する問題