PDA

View Full Version : QgraphicsView rubber band selection rectangle not visible



tarunrajsingh
29th March 2013, 07:42
I have a QgraphicsView widget with lots of items on scene.Iam panning the view on ctr+left mouse click and zooming it to rectangle of rubber band created with left mouse button drag. Iam not able to see rubber band selection rectangle (dotted lines) whereas rubberband selection functionality works fine.Can anybody help me understand this.I use these flags in my view

setTransformationAnchor(QGraphicsView::AnchorUnder Mouse);
setViewportUpdateMode(QGraphicsView:: SmartViewportUpdate);
setRenderHints(QPainter::HighQualityAntialiasing | QPainter::SmoothPixmapTransform);
setOptimizationFlag(QGraphicsView:: DontSavePainterState,true);
setCacheMode(QGraphicsView::CacheBackground);
setOptimizationFlag(QGraphicsView:: DontAdjustForAntialiasing);
setViewport(new QGLWidget);
below are my event handlers.

mouse press event handler

void MyView::mousePressEvent(QMouseEvent* event)
{
if(event->button()==Qt::LeftButton)
{
if(event->modifiers()==Qt::ControlModifier)
{
setDragMode(QGraphicsView::NoDrag);
m_rubberBandActive = false;
mousepressed=true;
m_lastDragPos = event->pos();
return;
}
else
{
setDragMode(QGraphicsView::RubberBandDrag);
m_rubberBandOrigin = event->pos();
m_rubberBandActive = true;
}
}
event->accept();
}
else
{
QWidget::mousePressEvent(event);
}
}

mouse move event

void MyView::mouseMoveEvent(QMouseEvent* event)
{
if(mousepressed)
{
QPointF delta = mapToScene(event->pos()) - mapToScene(m_lastDragPos);
this->panView(delta);
m_lastDragPos = event->pos();
return;
}
event->accept();
}



mouse release event Handler

void MyView::mouseReleaseEvent(QMouseEvent *event)
{
if (m_rubberBandActive)
{
QPoint rubberBandEnd = event->pos();
QRectF zoomRectInScene = QRectF(mapToScene(m_rubberBandOrigin),mapToScene(r ubberBandEnd));

fitInView(zoomRectInScene, Qt::KeepAspectRatio);
m_rubberBandActive = false;
}

mousepressed=false;
event->accept();
}

pan view

void MyView:: panView(QPointF delta)
{
QPoint viewCenter(viewport()->width() / 2 + delta.x(), viewport()->height() / 2 + delta.y());
QPointF newCenter = mapToScene(viewCenter);
centerOn(newCenter);
}

d_stranz
3rd April 2013, 17:44
Please use CODE tags when posting source code. Click the "Go Advanced" button when writing your message; CODE tags will be inserted when you click the "#" toolbar button. Paste your code between them.

Did you call QGraphicsView::setInteractive() with "true" when constructing your view?

In my code, I use an "overlay widget" for rubberband interaction. This is a QWidget exactly the same size as the plot canvas, placed exactly over the canvas rect. When the mouse is pressed, the window is shown and the rubberband is displayed there. When the mouse is released, I issue a signal from the overlay widget giving the coordinates of the selected rect, then I hide the overlay.

I have found that when there are a very large number of items in the scene, using the drag mode of the QGraphicsView directly (as you are doing) does not give reliable performance. I think what is happening is that the scene is completely redrawn for every movement of the mouse, not only slowing everything down to almost a halt, but also making it seem like the rubberband is not being drawn. It is, but the scene isn't being redrawn fast enough. You can verify this by moving the mouse very, very slowly so the scene has enough time to be redrawn between movements. You should see the rubberband then.

With the overlay widget, the rubber band is being drawn on the overlay widget, not on the graphics view, so there are no paint events for the graphics view until the overlay is removed. You can guarantee this if you make the overlay widget opaque, and replace its background with a pixmap of the graphics view's contents - when the mouse is pressed, you render the graphics view to a pixmap, and paint that pixmap in the overlay. Since it is opaque, none of the paint events get through to the graphics view underneath, and your rubberbanding is quick and responsive.