2010-12-02 5 views
6

J'ai une implémentation QGraphicsItem personnalisée. Je dois être en mesure de limiter où l'élément peut être déplacé - je, e. restreindre à une certaine zone. Lorsque j'ai vérifié la documentation Qt est ce ce qu'il suggère:QGraphicsItem validant un changement de position

QVariant Component::itemChange(GraphicsItemChange change, const QVariant &value) 
{ 
    if (change == ItemPositionChange && scene()) { 
     // value is the new position. 
     QPointF newPos = value.toPointF(); 
     QRectF rect = scene()->sceneRect(); 
     if (!rect.contains(newPos)) { 
      // Keep the item inside the scene rect. 
      newPos.setX(qMin(rect.right(), qMax(newPos.x(), rect.left()))); 
      newPos.setY(qMin(rect.bottom(), qMax(newPos.y(), rect.top()))); 
      return newPos; 
     } 
    } 
    return QGraphicsItem::itemChange(change, value); 
} 

Donc, fondamentalement, vérifier la position passée à itemChange, et si vous ne l'aimez pas, changer et retourner la nouvelle valeur.

Semble assez simple, sauf qu'il ne fonctionne pas réellement. Quand j'ai vérifié la pile d'appels, je vois que itemChange est appelé depuis QGraphicsItem :: setPos, mais il ne regarde même pas la valeur de retour. Il n'y a donc aucune raison pour que je retourne une position modifiée, personne ne la regarde. Voir le code de QGraphicsItem.cpp

// Notify the item that the position is changing. 
    const QVariant newPosVariant(itemChange(ItemPositionChange, qVariantFromValue<QPointF>(pos))); 
    QPointF newPos = newPosVariant.toPointF(); 
    if (newPos == d_ptr->pos) 
     return; 

    // Update and repositition. 
    d_ptr->setPosHelper(newPos); 

    // Send post-notification. 
    itemChange(QGraphicsItem::ItemPositionHasChanged, newPosVariant); 
    d_ptr->sendScenePosChange(); 

Des suggestions? J'espérais éviter de ré-implémenter tout le comportement de cliquer-glisser moi-même en utilisant le mouse-down mouse-move etc ..., mais je suppose que je devrai si je ne peux pas trouver une meilleure idée.

Répondre

4

Je ne l'ai pas réellement essayé mais il me semble qu'il vérifie la position de retour. La position restreinte renvoyée est utilisée dans le constructeur de newPosVariant pour être convertie en newPos. Il est ensuite utilisé pour définir la position de l'élément s'il est différent de celui en cours.

+1

Ah! Je vois mon problème. Dans mon code actuel, je vérifiais ItemPositionHasChanged au lieu de ItemPositionChange. Ce qui signifie que toutes mes vérifications de position se passaient dans le mauvais appel à itemChange - celui qui ne vérifie pas le type de retour. Merci de m'avoir fait regarder à nouveau ce que je faisais. C'était idiot de ma part. – Liz