4

I've want to implement a scroll/pan-feature on a QGraphicsView in my (Py)Qt application. It's supposed to work like this: The user presses the middle mouse button, and the view scrolls as the user moves the mouse (this is quite a common feature).
I tried using the scroll() method inherited from QWidget. However, this somehow moves the view instead - scrollbars and all. See picture.
So, given that this is not the way I'm supposed to do this, how should I? Or is it the correct way, but I do something else wrong? The code I use:

   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])

It works as I expect, except for the whole move-the-widget business.

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

3
  • What widget type is self.ui.imageArea? Is it a QScrollArea, QGraphicsArea, or something else? Commented Jul 9, 2009 at 16:51
  • Oh, didn't mention it in the text, but in the title. It's a QGraphicsView. Commented Jul 10, 2009 at 7:02
  • So is the QScrollArea inside the QGraphicsScene that the view is displaying? Commented Jul 10, 2009 at 13:42

4 Answers 4

4

My addition to translate() method. It works great unless you scale the scene. If you do this, you'll notice, that the image is not in sync with your mouse movements. That's when mapToScene() comes to help. You should map your points from mouse events to scene coordinates. Then the mapped difference goes to translate(), voila viola- your scene follows your mouse with a great precision.

For example:

QPointF tmp2 = mapToScene(event->pos());
QPointF tmp = tmp2.mapToScene(previous_point);
translate(tmp.x(),tmp.y());
Sign up to request clarification or add additional context in comments.

Comments

3

I haven't done this myself but this is from the QGraphicsView documentation

... When the scene is larger than the scroll bars' values, you can choose to use translate() to navigate the scene instead.

By using scroll you are moving the widget, translate should achieve what you are looking for, moving the contents of the QGraphicsScene underneath the view

4 Comments

Well, the scene isn't larger than the allowed values of the scrollbars, so it shouldn't be a problem. But I tried translating too, but that just sort of made the image shudder back and forth. I think it got re-centered automatically?
I am looking at the docs, have you tried setDragMode(QGraphicsView::ScrollHandDrag) and is the value of interactive set to true ?
re translate, you need view.setTransformationAnchor( QtGui.QGraphicsView.NoAnchor ) else translate() is a noop ?!
Harald: Thanks for your suggestiong, I just tried that. It changed how the widget moved around, but it was still the widget that got moved.
1

Answer given by denis is correct to get translate to work. The comment by PF4Public is also valid: this can screw up scaling. My workaround is different than P4FPublc's -- instead of mapToScene I preserve the anchor and restore it after a translation:

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)

Comments

0

You can set the QGraphicsScene's area that will be displayed by the QGraphicsView with the method QGraphicsView::setSceneRect(). So when you press the button and move the mouse, you can change the center of the displayed part of the scene and achieve your goal.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.