2016-10-31 11 views
2

У кого-нибудь есть лучший способ сдержать ребенка от QGraphicsItem до сцены?Сдерживание ребенка QGraphicsItem к сцене?

Я успешно связал родителя QGraphicsItem с его сценой, переопределив itemChange, но теперь мне нужно сделать то же самое для ребенка QGraphicsItem.

Пример использования регистра:

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

Этот код работает ... по большей части. Единственная проблема заключается в скорости он QGraphicsItem «s при ударе по обе стороны будет влиять на его endstop положение:

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

Для родительского элемента, я использовал: newPos.setX(qMin(scRect.right(), qMax(newPos.x(), scRect.left()))); который работал отлично, но я озадачен, чтобы как или если бы я мог использовать это здесь.

+0

К месту или для просмотра? – dtech

+0

Проблема заключается в коде, который добавляет скорость, прежде чем вы вызовете 'setPos', вам не нужно делать это в' itemChange'. Можете ли вы показать этот код? – TheDarkKnight

+0

У меня нет этого кода. Ползунок движется так же быстро, как и мышца. –

ответ

2

Во-первых, чтобы быть конкретным, сцены эффективно не имеют границ. То, что вы пытаетесь сделать, это ограничить элемент прямоугольником сцены, который вы установили в другом месте.

Проблема, которую я вижу, заключается в использовании сценария. Это ItemPositionChange; объект scenePos объекта еще не обновлен новой позицией, поэтому, когда вы проверяете, что scenePos находится вне сцены, вы действительно проверяете результат последнего изменения позиции, а не текущий. Из-за этого ваш предмет попадает прямо к краю прямоугольника сцены, а затем прилипает туда. Как далеко от края зависит, насколько быстро вы двигаете мышь, которая определяет, сколько расстояния между уведомлениями 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 для сравнения.

Обратите внимание, что я не предполагал, что левый край сценыRecT равен 0. Я уверен, что это то, что вы закодировали, где вы установили sceneRect, но используя фактическое левое значение, а не предполагая, что оно 0, устраняет любые проблемы, если вы в конечном итоге меняете диапазон координат сцены, с которыми вы планируете работать.

Я использовал «левый» вместо «x» на сцене. Обращайтесь к вызову только потому, что он параллелен использованию «правой» для другой стороны. Они точно такие же, но я думаю, что в этом случае он выглядит немного лучше.

+0

'mapToScene' была функцией, которую мне нужно было исследовать. И после переделать с помощью 'mapFromScene',' mapToScene', 'mapFromParent' и' mapToParent', я нашел именно то, что мне нужно: 'mapToScene (mapFromParent (newPos))' –