2010-12-02 16 views
6

Tengo una implementación personalizada de QGraphicsItem. Necesito poder limitar dónde se puede mover el artículo: i, e. restringirlo a un área determinada. Cuando comprobé la documentación de Qt esto es lo que sugiere:QGraphicsItem validación de un cambio de posición

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

Así que, básicamente, comprobar la posición pasó a itemChange, y si no te gusta, cambiarlo y volver el nuevo valor.

Parece bastante simple, excepto que en realidad no funciona. Cuando revisé la pila de llamadas, veo que ItemChange se llama desde QGraphicsItem :: setPos, pero ni siquiera mira el valor devuelto. Entonces no hay ningún propósito para mí que devuelva una posición modificada, nadie lo está mirando. Ver código 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(); 

¿Alguna sugerencia? Esperaba evitar volver a implementar todo el comportamiento de hacer clic y arrastrar usando el movimiento del mouse hacia abajo, etc., pero supongo que tendré que hacerlo si no puedo encontrar una mejor idea.

Respuesta

4

No lo probé, pero me parece que está comprobando la posición de retorno. La posición restringida devuelta se utiliza en el constructor de newPosVariant para convertirse a newPos. Luego se usa para establecer la posición del artículo si es diferente del actual.

+1

¡Ah! Veo mi problema En mi código actual, estaba verificando ItemPositionHasChanged en lugar de ItemPositionChange. Lo que significa que todas las comprobaciones de mi posición estaban sucediendo en la llamada incorrecta a ItemChange - la que no marca el tipo de devolución. Gracias por hacerme ver de nuevo lo que estaba haciendo. Eso fue tonto de mi parte – Liz

Cuestiones relacionadas