GraphicsView: Update region issue
I use GraphicsView to draw a gauge instrument, looking a bit like an old-fashioned tachometer – like this:
For optimization reasons, I would like to minimize the area that I need to redraw, that is, the “update regions”.
Normally, the background is static, and only the needle moves. Therefore, it should be enough to re-draw the area the needle is on.
The needle itself is a QGraphicsPixmap item, which displays a pixmap of a needle. Everything in the pixmap that does not need to show is transparent via alpha channel (as defined in the source PNG file).
All I do is to rotate the needle using the following code, whenever the value changes:
I set the needle’s BoundingRegionGranularity to 1.0, in order to minimize the amount of pixels needed in a refresh. This is optimal for the embedded device I am deploying to. Since the QGraphicsPixmapItem calculates it’s shape from the pixmap, and considers transparency (QGraphicsPixmapItem::ShapeMode is MaskShape), I assumed that exactly the area of the needle would be re-drawn, nothing more.
Because I am paranoid, I check what Qt actually does, and it isn’t what I expect.
I colorize the background with a semi-transparent, ever-changing color (the color is calculated based on the system time). Therefore, I see which areas are re-drawn, and which are not.
The result is visible in the following image:
As you can see, the needle has an angle of approximately -45° (compared to the vertical coordinate system axis). The last area to be re-drawn is a purple rectangle that covers both the visible part of the needle, as well as the transparent parts down to the center of the gauge.
It should not be a rectangle! It should be shapes of the needle, like snow angles!
Question: Why does the update region end up as a rectangle, instead of being shaped like the visible part of the needle?
I checked the following:
1) I am calling no updates except an update to the needle itself
2) The needle is a QGraphicsPixmapItem, the ShapeMode is MaskShape
3) The BoundingRegionGranularity is 1.0 on both the QGraphicsPixmapItem and it’s parent widget (although I would see the latter as unnecessary)
4) My ViewportUpdateMode is “Minimal”
5) I have set the Needles’ flag “QGraphicsItem::ItemClipsToShape”
How do I fix that? How do I even analyze whether the problem is in the shape() returned by the QGraphicsPixmapItem, or elsewhere? How do I debug a QPainterPath or a QBitmap? Why does the rotation in combination with a high boundingRegionGranularity not result, at least in a narrow rectangle tilted to -45°?
Here Is a QML dial example [doc.qt.nokia.com] that does the same thing as you want.
Maybe you would consider using Qml. It’s really usefull in projects like this.
Well, I have tried various things, and found out the following:
The shape of the QGraphicsPixmapItem is ok. The problem lies elsewhere:
For some reason, multiple small update regions are merged to one large update rectangle. Even if I explicitly provide two update rectangles, a single larger rectangle is created from it.
Does anyone have an idea how I influence that behaviour?