4

QGraphicsview has a method setDragMode(ScrollHandDrag) to enable panning with the left mouse click. But I wanted to enable panning when the mouse wheel is clicked(the middle button) and created the following custom implementation to pan:

//Within a custom derived class of QGraphicsView
//pan is true when wheel is clicked and false when released
//last Pos is defined somewhere else in the class

void GridView::mouseMoveEvent(QMouseEvent *event){
     if(pan){
         QPointF currentPos = event->pos();
         QPointF relPos = currentPos - lastPos;
         lastPos = currentPos;

         //this is what creates the panning effect
         translate(relPos.x(), relPos.y());
     }
     QGraphicsView::mouseMoveEvent(event);
}

This works fine for the most part. But for example, if I scale the identity matrix by 1,000,000 this method fails and stops panning (as if the view got stuck). This problem doesn't arise when I use setDragMode()

What would be the proper custom implementation of setDragMode() so it is enabled by the wheel click?

lambda
  • 1,225
  • 2
  • 14
  • 40

1 Answers1

10

This works for me... it tricks Qt into thinking the user is pressing the left mouse button when he's really pressing the middle one.

void GridView :: mousePressEvent(QMouseEvent * e)
{
   if (e->button() == MidButton)
   {
      QMouseEvent fake(e->type(), e->pos(), LeftButton, LeftButton, e->modifiers());
      QGraphicsView::mousePressEvent(&fake);
   }
   else QGraphicsView::mousePressEvent(e);
}

void GridView :: mouseReleaseEvent(QMouseEvent * e)
{
   if (e->button() == MidButton)
   {
      QMouseEvent fake(e->type(), e->pos(), LeftButton, LeftButton, e->modifiers());
      QGraphicsView::mouseReleaseEvent(&fake);
   }
   else QGraphicsView::mouseReleaseEvent(e);
}
Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234
  • 1
    This is an excellent work around! I coupled it with calls to setInteractive true/false and setDragMode ScrollHandDrag/NoDrag for press and release events respectively – Shootfast Feb 11 '14 at 17:45
  • @Shootfast Great stuff. Did the same. – Oleh Prypin Sep 11 '14 at 13:44
  • 1
    This may not work as intended if you need LeftButton event for something else. An alternative approach is described here: https://stackoverflow.com/a/5156978/2055281 – user31208 Feb 03 '18 at 20:39
  • I think it will work as intended, since it doesn't change the GridView's responses to genuine left-button events in any way (left-button events simply fail the if e->button()==MidButton test and therefore the code calls up to the superclass the same as always) – Jeremy Friesner Feb 03 '18 at 21:45