Why does setTransform affect the boundingRect() ?
I set a transformation on a QGraphicsItem using setTransform.
Suddenly, my previously fine boundingRect() no longer makes any sense.
Please prove me wrong, but this is what I gathered from docs, source code and training documentation:
The boundingRect() is given in the coordinate system of that item's parent, except that the position 0/0 is the item's position within the parent.
This is also made clear by the fact how QGraphicsWidget implements it's boundingRect: It simply uses geometry().size(). Now the geometry() must be in parent coordinates (although the docs neglect to mention that), because "geometry() is equivalent to QRectF(pos(), size())" and since pos() must be in parent coordinates, it would not make any sense for size() to be in a different coordinate system.
setTransform is supposed to affect the item's coordinate system, not the parent's coordinate system.
Taken together, it simply does not make any sense for the boundingRect() to need any tweaks if I change the transformation of an item. Especially since QGraphicsWidget's implementation of boundingRect() breaks as soon as I change the transformation, this looks like a bug to me.
And no, I am not using any "ItemIgnores*Transformations" flags.
However, knowing I have been thinking about this too long, I might have dug my own logical hole. Can you see it?
A transformation can do the following (just to name a few examples):
- rotate an item
- change item position
- change item size
- change item shape
Now, out of those 4, three items change the overal shape of the item, and how much space it occupies on the screen. It seems natural to me, then, that the boudingRect should change after a transformation is applied.
The size an item occupies in screen pixels might change due to a transformation, that does not necessarily mean the boundingRect must change.
For example, if I render a rectangle of size 200x100 and give it the according boundingRect, the rectangle might actually occupy only 20x10 pixels at 10% zoom level. The item does not, and does not need to know about the zoom level.
[quote author="Asperamanca" date="1408027022"]For example, if I render a rectangle of size 200x100 and give it the according boundingRect, the rectangle might actually occupy only 20x10 pixels at 10% zoom level. The item does not, and does not need to know about the zoom level.[/quote]
Corect. But you are mixing a zoom level (which is about transforming the view/ scene) and setting a transformation on an item itelf. Those are 2 separate things. In case of zooming, you are right: there should be no need to change the bounding rect. But when you transform an item, the bounding rect will need an update.
[quote author="sierdzio" date="1408027456"] But when you transform an item, the bounding rect will need an update.[/quote]
And why should it be necessary? Technically, it's no big deal for the GraphicsView framework to determine the actual boundindRect (in screen pixels) based on the information available. Again, it comes down to which coordinate system the boundingRect is defined in.
Also, given you are right, why did nobody notice that the boundingRect-implementation of QGraphicsWidget makes no sense once you apply a transformation to the item itself?
Perhaps we both misunderstand something ;-)
Well, in fact, it's no big deal. I know how to write my code so it does what I want. It's just very frustrating that all the relevant places in the docs omit in which coordinate system important stuff is.
Turns out, it is a big deal after all, because the alternatives introduce all kinds of complications.
Also, I have found some interesting points in the docs:
bq. An item's transformation does not affect its own local geometry; all geometry functions (e.g., contains(), update(), and all the mapping functions) still operate in local coordinates
bq. Although the item's shape can be arbitrary, the bounding rect is always rectangular, and it is unaffected by the items' transformation.