handle
handle

Reputation: 6319

Setting exact view area (rect) of QGraphicsScene in QGraphicsView - a better fitInView()?

I am failing in trying to restore a particular view (visible area) in a subclassed QGraphicsView on a subclassed QGraphicsScene.

The visible rectangle of the scene viewed should be

mapToScene( rect() ).boundingRect()

which is

QRectF(27.8261,26.9565 673.043x507.826)

I obtain these values in the destructor of QGraphicsView, they seem valid.

After restoring the window geometry, I am using said values in the first QGraphicsView::resizeEvent (the first event has an invalid old size QSize(-1, -1)) in the attempt to restore the area shown in view using

fitInView( QRectF(....) , Qt::IgnoreAspectRatio);

This triggers a number of scrollContentsBy events before showing the view, another resize and scroll event after, then the mainwindow showEvent fires, causing more resize scroll and resize events. I am sure this sequence is neccessary for the GUI layout to build, but I am now confused as to how I could run fitInView once everything is set up.

Using a QTimer::singleShot to run the function well after the GUI is shown, I get approximately the desired result, but the matrix and viewed area differ:

ui->graphicsView->matrix();
ui->graphicsView->mapToScene( ui->graphicsView->rect()).boundingRect();

Before:

"[m11=1 m12=0 m21=0 m22=1 dx=0 dy=0] (x=27 y=27 w=774 h=508)"

Restored:

"[m11=0.954724 m12=0 m21=0 m22=0.954724 dx=0 dy=0] (x=17.8062 y=24.0907 w=810.705 h=532.091)"

So fitInView() does not serve my purpose very well - is there another, reliable way?

I'm using Qt 4.8.1 with MSVC2010


Another approach is to restore transform and window scroll position like so:

settings->setValue("view", mapToScene( rect() ).boundingRect() );
settings->setValue("transform", transform() );
settings->sync();

and restore them

QTransform trans = settings->value("transform", QTransform()).value<QTransform>();
QRectF view = settings->value( "view", QRectF() ).value<QRectF>();
setTransform( trans );
centerOn( view.center() );

But this method, too, has an offset.

Before

"[m11=4.96282 m12=0 m21=0 m22=4.96282 dx=0 dy=0] (x=29.6203 y=29.4188 w=155.96 h=104.981)"

After

"[m11=4.96282 m12=0 m21=0 m22=4.96282 dx=0 dy=0] (x=54.8076 y=53.8001 w=155.96 h=104.981)" 

An offset also is present when scrollbars are hidden. Moving the code to showEvent() does not affect result.

Upvotes: 0

Views: 1045

Answers (1)

handle
handle

Reputation: 6319

What is finally working: in showEvent, restore the transform, restore scroll-bar values:

setTransform( trans );
verticalScrollBar()->setValue( v );
horizontalScrollBar()->setValue( h );

Scroll bar visibility does not affect the view position and size, they are just "overlays".

Upvotes: 1

Related Questions