GraphicsView: Update region issue

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

    ! 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:


    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:

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

  • Moderators

    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.

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

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

Log in to reply

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.