views:

262

answers:

1

Hi, I am going to do pan/scale stuff on QGraphicsView.
So I read the documentation of QGraphicsView and see some utility functions like ensureVisible() and centerOn().
I think I understand what the documentation says but I can' t manage to write a working example.
Could you please write/suggest me an example code to understand the issue.

+1  A: 

Ton pan the view by a certain amount (for example in your view's mouseMoveEvent()), assuming MyView is a subclass of QGraphicsView (all the following code was ported from Python, I didn't test it):

void MyView::moveBy(QPoint &delta) 
{
    QScrollBar *horiz_scroll = horizontalScrollBar();
    QScrollBar *vert_scroll = verticalScrollBar();
    horiz_scroll->setValue(horiz_scroll.value() - delta.x());
    vert_scroll->setValue(vert_scroll.value() - delta.y());
}

To fit a rectangle specified in scene coordinates by zooming and panning:

void MyView::fit(QRectF &rect)
{
    setSceneRect(rect);
    fitInView(rect, Qt::KeepAspectRatio);
}

Note that if your scene contains non transformable items (with the QGraphicsItem::ItemIgnoresTransformations flag set), you'll have to take extra steps to compute their correct bounding box:

/**
 * Compute the bounding box of an item in scene space, handling non 
 * transformable items.
 */
QRectF sceneBbox(QGraphicsItem *item, QGraphicsItemView *view=NULL)
{
    QRectF bbox = item->boundingRect();
    QTransform vp_trans, item_to_vp_trans;

    if (!(item->flags() & QGraphicsItem::ItemIgnoresTransformations)) {
        // Normal item, simply map its bounding box to scene space
        bbox = item->mapRectToScene(bbox);
    } else {
        // Item with the ItemIgnoresTransformations flag, need to compute its
        // bounding box with deviceTransform()
        if (view) {
            vp_trans = view->viewportTransform();
        } else {
            vp_trans = QTransform();
        }
        item_to_vp_trans = item->deviceTransform(vp_trans);
        // Map bbox to viewport space
        bbox = item_to_vp_trans.mapRect(bbox);
        // Map bbox back to scene space
        bbox = vp_trans.inverted().mapRect(bbox);
    }

    return bbox;
}

In that case the bounding rect of your objects becomes dependent on the view's zoom level, meaning that sometimes MyView::fit() won't fit exactly your objects (for example when fitting a selection of objects from a largely zoomed out view). A quick and dirty solution is to call MyView::fit() repeatedly until the bounding rect naturally "stabilizes" itself.

Luper Rouch