2009-07-09 2 views
2

Je souhaite implémenter une fonction de défilement/panoramique sur un QGraphicsView dans mon application (Py) Qt. Il est censé fonctionner comme ceci: L'utilisateur appuie sur le bouton central de la souris, et la vue défile lorsque l'utilisateur déplace la souris (c'est une caractéristique assez courante).
J'ai essayé d'utiliser la méthode scroll() héritée de QWidget. Cependant, cela déplace la vue à la place - scrollbars et tout. Voir l'image. Donc, étant donné que ce n'est pas ce que je suis censé faire, comment le ferais-je? Ou est-ce la bonne façon, mais je fais quelque chose d'autre? Le code que j'utilise:Défilement de QGraphicsView par programmation

def __init__(self): 
     ... 

     self.ui.imageArea.mousePressEvent=self.evImagePress 
     self.ui.imageArea.mouseMoveEvent=self.evMouseMove 

     self.scrollOnMove=False 
     self.scrollOrigin=[] 

     ... 

    def evImagePress(self, event): 
     if event.button() == Qt.LeftButton: 
      self.evImageLeftClick(event) 
     if event.button() == Qt.MidButton: 
      self.scrollOnMove=not self.scrollOnMove 
      if self.scrollOnMove: 
       self.scrollOrigin=[event.x(), event.y()] 
    ... 

    def evMouseMove(self, event): 
     if self.scrollOnMove: 
      self.ui.imageArea.scroll(event.x()-self.scrollOrigin[0], 
            event.y()-self.scrollOrigin[1]) 

Cela fonctionne comme prévu, à l'exception de l'ensemble de l'entreprise move-the-widget.

Fails to scroll http://img55.imageshack.us/img55/3222/scrollfail.jpg

+0

Quel type widget est self.ui.imageArea? Est-ce un QScrollArea, QGraphicsArea ou autre chose? –

+0

Oh, ne l'ai pas mentionné dans le texte, mais dans le titre. C'est un QGraphicsView. – carlpett

+0

QScrollArea se trouve-t-il dans QGraphicsScene que la vue affiche? –

Répondre

3

Je ne l'ai pas fait moi-même, mais c'est de la documentation QGraphicsView

... Lorsque la scène est plus grande que les valeurs des barres de défilement, vous pouvez choisir de Utilisez translate() pour naviguer à à la place.

En utilisant scroll vous déplacez le widget, translate devrait réaliser ce que vous cherchez, déplacer le contenu du QGraphicsScene sous la vue

+0

Eh bien, la scène n'est pas plus grande que les valeurs autorisées des barres de défilement, cela ne devrait donc pas poser de problème. Mais j'ai essayé de traduire aussi, mais ça a fait trembler l'image d'avant en arrière. Je pense qu'il a été recentré automatiquement? – carlpett

+0

Je regarde les docs, avez-vous essayé 'setDragMode (QGraphicsView :: ScrollHandDrag)' et la valeur de 'interactive' est-elle définie sur' true'? –

+7

re traduire, vous avez besoin view.setTransformationAnchor (QtGui.QGraphicsView.NoAnchor) else translate() est un noop?! – denis

0

Vous pouvez définir la zone du QGraphicsScene qui sera affiché par le QGraphicsView avec la méthode QGraphicsView::setSceneRect(). Ainsi, lorsque vous appuyez sur le bouton et déplacez la souris, vous pouvez changer le centre de la partie affichée de la scène et atteindre votre objectif.

4

Mon ajout à la méthode translate(). Cela fonctionne très bien, sauf si vous mettez à l'échelle la scène. Si vous faites cela, vous remarquerez que l'image n'est pas synchronisée avec les mouvements de votre souris. C'est alors que mapToScene() vient aider. Vous devez mapper vos points des événements de la souris aux coordonnées de la scène. Alors la différence mappée va à translate(), voila viola- ta scène suit ta souris avec une grande précision.

Par exemple:

QPointF tmp2 = mapToScene(event->pos()); 
QPointF tmp = tmp2.mapToScene(previous_point); 
translate(tmp.x(),tmp.y()); 
1

Réponse donnée par denis est correct pour obtenir la traduction de travailler. Le commentaire de PF4Public est également valide: cela peut nuire à la mise à l'échelle. Ma solution est différente de celle P4FPublc - au lieu de mapToScene je conserve l'ancre et reconstitue après traduction:

previousAnchor = view.transformationAnchor() 
#have to set this for self.translate() to work. 
view.setTransformationAnchor(QGraphicsView.NoAnchor) 
view.translate(x_diff,y_diff) 
#have to reset the anchor or scaling (zoom) stops working: 
view.setTransformationAnchor(previousAnchor)