December 13, 2011

Asperamanca Asperamanca
Robot Herder
732 posts

GraphicsView: Update region issue


I use GraphicsView to draw a gauge instrument, looking a bit like an old-fashioned tachometer – like this:

Gauge instrument

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:

  1. m_pNeedle->setRotation(newAngle);

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:

Colorized update regions

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°?

Any ideas?

3 replies

December 13, 2011

Eddy Eddy
Area 51 Engineer
1571 posts

Here Is a QML dial example [] that does the same thing as you want.

Maybe you would consider using Qml. It’s really usefull in projects like this.


Qt Certified Specialist
Nokia Qt Ambassador

December 13, 2011

Asperamanca Asperamanca
Robot Herder
732 posts

No QML. It’s a project-wide decision. The reasons are many-fold, and do not belong in this thread.

December 13, 2011

Asperamanca Asperamanca
Robot Herder
732 posts

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?

  ‹‹ [SOLVED] QNetworkAccessManager get      Any tutorial for using .ui file ››

You must log in to post a reply. Not a member yet? Register here!