[Qt-interest] Unable to get sensible coordinate mappings

Andrew Hodgkinson ahodgkinson at endurancetech.co.uk
Mon May 18 19:35:56 CEST 2009


David Boddie wrote:

> I suspect that this may be a side effect of your item's paint()
> implementation.

Yep, that's the bottom line. The 'mapTo/mapFrom' family of methods turn
out to only work when used with 'QGraphicsItem::setTransform()' and 
related methods. QGraphicsItem's documentation for setTransform says:

   "To simplify interation with items using a transformed view,
    QGraphicsItem provides mapTo... and mapFrom... functions that can
    translate between items' and the scene's coordinates [...]"

The path I took through the documentation by chance meant that the 
window/viewport solution was the first one to present itself. It has 
analogies to an approach in another system with which I'm more familiar, 
so it seemed like a decent enough solution. As a result I'd never read 
the documentation for the QGraphicsItem transformation methods since I 
wasn't using them...

It looks like the whole of QPainter's coordinate transformations 
mechanism is essentially incompatible with the coordinate mapping methods 
in QGraphicsItem. Coordinates inside a paint() routine which employs 
painter transformations effectively become different from the item's 
general local coordinates and it's up to the application to deal with 
that. Fair enough.

If the description of transformations in both the QGraphicsItem and 
QPainter documentation could refer to each other and mention this issue 
it would be handy to prevent others making the same mistake - OTOH maybe 
I'm just stupid :-D

> You just happened to choose to use setWindow() and setViewport(),
> which cause problems with the painter's state.

I wasn't aware of such potential problems clouding the issue. Since it
looks like the use of item transformations is the way forward, as you
recommended in your previous reply, the viewport and window code will be
removed so any related side-effects ought to go away.

 >    painter.save();
 >    painter.translate(sceneSafeW, sceneSafeH);
 >    painter.scale(safeSceneRect.width()/bannerArea.width(),
 >                  safeSceneRect.height()/bannerArea.height());
 >    // Do your painting here...
 >    painter.restore();

That's the nub of it, except the translation and scaling will be done by
the item, I think, rather than in the painter. It also means the painter
code will get faster since it won't have to worry about setting up the 
transformation each time it gets called.

 > Your boundingRect() implementation would be as you described:
 >
 > QRectF SomeClassName::boundingRect() const
 > {
 >      return QRectF(bannerArea);
 > }

Given the above, if I've not specified any kind of transformation for the 
item itself, then scene coordinates and item coordinates amount to one 
and the same thing. This explains the behaviour I was seeing with various 
values returned from this particular method. So as you said...

>>> If you're happy with the idea of scaling up from a scene
>>> containing items placed within a 1280x720 rectangle then one thing
>>> you might want to try is to set a transform on the view, mapping
>>> scene coordinates to the screen geometry.

...this looks like the way forward.

Thanks for your help!

-- 
TTFN, Andrew Hodgkinson
Find some electronic music at:     Photos, wallpaper, software and more:
http://pond.org.uk/music.html                        http://pond.org.uk/



More information about the Qt-interest-old mailing list