2016-10-24 1 views
2

J'essaye de contraindre correctement le mouvement d'un QGraphicsItem (spécifiquement QGraphicsRectItem) sans changer le comportement natif pour fonctionner comme une barre de défilement sur l'axe X.Contraindre mouvement QGraphicsItem avec mouseMoveEvent

J'ai essayé de remplacer la fonction mouseMoveEvent, mais j'ai ensuite besoin de réécrire le comportement du rectangle dans les directions X et Y. Au mieux, je peux obtenir le rectangle à accrocher à une seule position avec la souris. (Ici, le rectangle se cassera si la souris il tient au milieu):

void SegmentItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event) 
{ 
    setY(0); 
    setX(event->scenePos().x() - boundingRect().width()/2); 
} 

Je regarde itemChange en ce moment, comme décrit here, mais il semble un peu trop compliqué et pas tout à fait élégante. EDIT: Cela devrait fonctionner, mais je ne peux pas le forcer à travailler. Y at-il un moyen de simplement contraindre le mouvement de l'axe Y?

(Je vais aussi avoir besoin de créer de fins de course pour la barre de défilement, mais plus tard.)

+1

La solution itemChange liée est la solution, et aussi très élégante – Fabio

+0

Cool, mais il ne semble rien limiter actuellement. J'ai lu _ "L'implémentation par défaut ne fait rien, et renvoie la valeur." _ Sur la [Page de référence de la classe] (http://doc.qt.io/qt-4.8/qgraphicsitem.html#itemChange) Savez-vous ce dont j'ai besoin? changer? –

Répondre

1

Je bricolé avec le code de la itemChange classe Page de référence, et amélioré si les quatre coins de ma QGraphicsRectItem demeureraient dans le QGraphicsScene:

QVariant SegmentItem::itemChange(GraphicsItemChange change, const QVariant &value) 
{ 
    if (change == ItemPositionChange && scene()) { 
     // value is the new position. 
     QPointF newPos = value.toPointF(); 
     QRectF rect = scene()->sceneRect(); 
     rect.setWidth(rect.width() - boundingRect().width()); 
     rect.setHeight(0); 
     if (!rect.contains(newPos)) { 
      // Keep the item inside the scene rect. 
      newPos.setX(qMin(rect.right(), qMax(newPos.x(), rect.left()))); 
      newPos.setY(2); 
      return newPos; 
     } 
    } 
    return QGraphicsItem::itemChange(change, value); 
} 
1

Pour répondre à l'autre partie de votre question sur la limitation du mouvement à une seule direction ... utilisez la même structure de changement d'élément que celle décrite dans la réponse ci-dessus. La seule chose supplémentaire que vous devez faire est de transférer la coordonnée X ou Y actuelle de votre objet à la nouvelle position avant de la renvoyer. Cette ligne permet Y de suivre la souris, mais conserve X le même (ie mouvement est limitée à la verticale):

newPos.setX (this->pos().x()); 

De même, pour permettre X de suivre la souris, mais gardez Y le même (à savoir le mouvement est restreint à l'horizontale):

newPos.setY (this->pos().y()); 

Avec la notification ItemPositionChange, n'a pas encore changé la position actuelle de l'élément, de sorte que vous pouvez manipuler la nouvelle position comme vous le souhaitez avant de retourner la nouvelle valeur.

+0

Cool, cela rend les choses plus faciles aussi! –