2016-10-31 4 views
2

누구든지 QGraphicsItem의 자식을 장면에 구속하는 더 좋은 방법이 있습니까?하위 QGraphicsItem을 장면에 제한하겠습니까?

itemChange을 재정 의하여 정상적으로 QGraphicsItem의 부모를 제한했지만, 지금은 자식 QGraphicsItem에 대해서도 동일한 작업을 수행해야합니다.

예 사용의 경우는 :

An Example Use Case with two handles (children) and a bar (parent)

이 코드는 대부분 ... 작동합니다. 상위 항목에 대해

QVariant SizeGripItem::HandleItem::itemChange(GraphicsItemChange change, 
               const QVariant &value) 
{ 
    QPointF newPos = value.toPointF(); 
    if (change == ItemPositionChange) 
    { 
     if(scene()) 
     { 
      newPos.setY(pos().y()); // Y-coordinate is constant. 

      if(scenePos().x() < 0) //If child item is off the left side of the scene, 
      { 
       if (newPos.x() < pos().x()) // and is trying to move left, 
       { 
        newPos.setX(pos().x()); // then hold its position 
       } 
      } 
      else if(scenePos().x() > scene()->sceneRect().right()) //If child item is off the right side of the scene, 
      { 
       if (newPos.x() > pos().x()) //and is trying to move right, 
       { 
        newPos.setX(pos().x()); // then hold its position 
       } 
      } 
     } 
    } 
return newPos; 
} 

, 내가 사용 : 유일한 문제는 endstop 위치에 영향을 미칠 것입니다 양쪽을 타격 할 때 QGraphicsItem의 속도입니다 완벽하게 작동 newPos.setX(qMin(scRect.right(), qMax(newPos.x(), scRect.left()))); ,하지만 난에로 난처한 상황에 빠진거야 내가 어떻게 여기 그것을 사용할 수 있는지.

+0

장면을 보거나 보시겠습니까? – dtech

+0

문제는 속도를 추가하는 코드에 있으며,'setPos'를 호출하기 전에'itemChange'에서 이것을하지 않아도됩니다. 그 코드를 보여줄 수 있습니까? – TheDarkKnight

+0

그 코드가 없습니다. 슬라이더는 마우스가 끌 때처럼 빠르게 움직입니다. –

답변

2

우선, 장면은 효과적으로 경계가 없습니다. 당신이하려는 것은 당신이 다른 곳에서 설정 한 장면 사각형에 항목을 구속하는 것입니다.

내가보기에 문제는 scenePos를 사용함에 있습니다. 이것은 ItemPositionChange입니다. 항목의 scenePos가 아직 새 위치로 업데이트되지 않았으므로 scenePos가 장면 rect에서 벗어 났는지 확인하면 실제로 현재 위치가 아닌 마지막 위치 변경 결과를 확인하고있는 것입니다. 이 때문에 항목은 장면 직사각형의 가장자리에서 끝나고 거기에 붙습니다. 가장자리에서 얼마나 멀리 떨어져 있는지는 마우스를 움직이는 속도에 달려 있습니다. 마우스를 움직이면 ItemPositionChange 알림 사이의 거리가 달라집니다.

대신에 새 위치를 장면 사각형과 비교 한 다음 반환 된 값을 장면 사각형 내에 포함시켜야합니다. 당신은 현장에서 새로운 위치 비교를 할 좌표가 필요, 그래서 당신은 같은 것을 필요

QPoint new_scene_pos = mapToScene (new_pos); 

if (new_scene_pos.x() < scene()->sceneRect().left()) 
    { 
    new_scene_pos.setX (scene()->sceneRect().left()); 
    new_pos = mapFromScene (new_scene_pos); 
    } 

을이 분명히, 전체 코드 아니지만, 이들은 당신이 그것을 유지해야 할 변환 및 검사입니다 왼쪽에 오른쪽이 매우 비슷하기 때문에 비교를 위해 new_scene_pos를 사용하십시오.

sceneRecT의 왼쪽 가장자리가 0이라고 가정하지 않았습니다. sceneRect를 어디에 설정했는지는 확실하지만 실제 왼쪽 값을 0으로 가정하지 않고 문제가 있으면 나중에 작업을 계획하고있는 장면 좌표 범위를 변경하게됩니다.

sceneRect 호출에서 "x"대신 "left"를 사용했습니다. 단지 다른 쪽에서 "right"를 사용하기 때문입니다. 그것들은 정확히 똑같지 만,이 경우 약간 더 잘 읽힌다고 생각합니다.

+0

'mapToScene'은 제가 연구 할 필요가있는 기능이었습니다. 그리고'mapFromScene','mapToScene','mapFromParent','mapToParent'로 꼼꼼히 살펴본 후 필자가 필요한 것을 정확히 발견했습니다 :'mapToScene (mapFromParent (newPos))' –