[PyQt] Various problems with QGraphicsView

Luke Campagnola lcampagn at email.unc.edu
Thu May 29 06:21:03 BST 2008


Hello again,
I am trying to implement a subclass of QGraphicsView that allows the
user to pan its contents by dragging with the middle mouse button and
scale by dragging with the right button. for various reasons, I do not
wish to use the built-in pan and zoom features in QGraphicsView. I
have read several posts online from people trying to accomplish
similar tasks but haven't really seen any satisfactory answers, and
I've been banging my head against this problem for a long while now.

Here is my basic approach: subclass QGraphicsView, reimplement all
mouse event functions so that I can catch the ones I recognize,
translate/scale the graphicsview, and pass on the remaining events.

Here are the problems I have run into:

  - If I catch ALL mouse events and never pass any on to the
QGraphicsView handlers, everything works fine. If, however, I do pass
some (but not all) events to the superclass, then I start to get some
very erratic behavior--maybe 1 out of every 100 mouse events has the
incorrect position, sometimes more. I've attached a program that
demonstrates this--you can drag with the right mouse button with no
trouble until the left mouse button (which is passed on to the
superclass) is clicked. After clicking the left mouse button, dragging
with the right mouse button should work most of the time but
occasionally the scene will jump erratically.

  - If, on the other hand, I pass ALL events to the superclass, then
every once in a while the mouseMoveEvent will start getting called
repeatedly in the absence of any events, usually tying up the CPU in
the process.

  - self.translate() does not work (seemingly under any
circumstances?). This has been discussed a few times before, and seems
to be caused by the graphicsView wanting to automatically center the
scene contents after translating them. My workaround looks like this
(working example attached):
      - in GraphicsView.__init__(), I have:
         self.setTransformationAnchor(QtGui.QGraphicsView.NoAnchor)
         self.setSceneRect(QtCore.QRectF(-1e100, -1e100, 1e100, 1e100))
      - Instead of using self.translate(x, y), I use:
          m = self.matrix()
          m.translate(x, y)
          self.setMatrix(m)
  I don't know exactly all of these together produce a workable
solution, but it seems like a lot of work to accomplish such a simple
task.

  - It is difficult to get full control of the viewport, presumably
because QAbstractScrollArea (or possibly QGraphicsView?) likes to move
the scene around without telling me (particularly when resizing the
window). My workaround to this has been to reset any unexpected
transformations like this:
    self.resetMatrix()
    center = self.mapToScene(self.width()/2., self.height()/2.)
    m = QtGui.QMatrix()
    m.translate(center.x(), center.y())
    self.setMatrix(m)
  I have left this out of the attached example, and as a result I know
no reliable way of knowing where exactly my graphics are drawn within
the widget.

  - It appears that the event object that gets passed to the
mouseEvent functions is being reused. This caused an unexpected (but
easily fixed) problem for me: In order to allow scene panning/scaling,
I need to record the event.pos() for every mouse event so that I can
compare the previous event position to the current event position.
Since the event object is reused, however, I find that the position I
stored as the "previous position" has already been updated to the
current position. For example:
  ## Does not work
  self.lastMousePosition = event.pos()
  ## Workaround
  self.lastMousePosition = QPoint(event.pos().x(), event.pos().y())


In summary, my questions:
0. Why might I be having so much difficulty handling mouse events?
1. Is there a better / recommended way to accomplish the type of user
interaction I'm after?
2. Is there some unambiguous way to set the transformation matrix used
by QGraphicsView that will not be interfered with?
3. Is there a simple way to make translate() work?

I'd love to hear any workable solutions other people have found.. I've
been tempted to just go back to using QPainter, but the features in
QGraphicsView are just too good to pass up :)
Thanks!
Luke


More information about the PyQt mailing list