Important: Please read the Qt Code of Conduct -

QQuickPaintedItem rotation causing aliasing

  • Hi,

    I'm working on implementing a custom round rectangle using QQuickPaintedItem so that I can change each corner radii independently and I'm running into an issue with rotating the object. Antialiasing seems to be working properly when the object is painted, but when I rotate the object via QML, aliasing appears along the diagonal edges of the rectangle. I can "hack" a fix to this by increasing the item's height and width and draw the rectangle inside the bounds of the item, but this solution requires a lot of hacky code.

    No rotation:

    Rotation with jaggies:

    Here's my paint method:

        double buffer = 0; //Used to draw inside the item instead of on the edges
            buffer += 1;
        path.moveTo(width() - topRightRadius() - buffer, buffer);
        //Top horizontal
        path.lineTo(topLeftRadius() + buffer, buffer);
        //Top left radius
        path.arcTo(buffer, buffer, topLeftRadius(), topLeftRadius(), 90, 90);
        //Left vertical
        path.lineTo(buffer, height() - bottomLeftRadius() + buffer);
        //Bottom left radius
        path.arcTo(buffer, height() - bottomLeftRadius() - buffer, bottomLeftRadius(), bottomLeftRadius(), 180, 90);
        //Bottom horizontal
        path.lineTo(width() - bottomRightRadius() - buffer, height() - buffer);
        //Bottom right radius
        path.arcTo(width() - bottomRightRadius() - buffer, height() - bottomRightRadius() - buffer, bottomRightRadius(), bottomRightRadius(), 270, 90);
        //Right vertical
        path.lineTo(width() - buffer, topRightRadius() + buffer);
        //Top right radius
        path.arcTo(width() - topRightRadius() - buffer, buffer, topRightRadius(), topRightRadius(), 0, 90);
        QBrush brush(QColor("#53b748"));
        painter->setRenderHint(QPainter::Antialiasing, true);

    Is there a fix for this? A better way to implement what I want? I'm open to any and all suggestions.

  • Moderators

    how do you rotate via QML? are you sure is in exact 90 degree steps?

    A workaround could be to bind the antialiasing property to rotation % 90.0 !== 0.0

  • @raven-worx

    I only want to rotate 5 degrees. I want to rotate when the item is dragged, so I have:

    rotation: ? 5 : 0

  • Moderators

    also make sure that you round the x and y coordinates after the drag has finished.
    Ensuring that the pos and size is even on pixels should prevent the need for antialiasing

  • @raven-worx
    I'm not sure what you mean. Even if I just rotate it in place without dragging it the aliasing still appears:

    rotation: 5

  • Moderators

    @zhannum said in QQuickPaintedItem rotation causing aliasing:

    I'm not sure what you mean.

    i meant when you are finished with dragging, you should ensure that the item's x and y coordinate and its width and height is not any floating value

    Even if I just rotate it in place without dragging it the aliasing still appears

    this doesnt look very antialiased to me?
    your first screenshot does though.

  • @raven-worx

    The x and y of the object after a drop event are set in QML, and are always set to integer values.

    this doesnt look very antialiased to me?
    your first screenshot does though.

    I agree. The jagged aliasing is what I'd like to fix. Basically how the diagonal line is made up of small horizontal lines, giving the appearance of steps.

    With my hacky fix I've implemented, this is what the result looks like, which is what I want:

    To better illustrate how I'm "hacking" a solution, i've set the fillColor of the item to white:

    You can see that the edges of the QQuickItem become jagged when rotated.

  • Moderators

    @zhannum said in QQuickPaintedItem rotation causing aliasing:

    I agree. The jagged aliasing is what I'd like to fix

    now i finally got you.
    You may want to read the following. If you use OpenGL?

    so you might want to try msaa. I assume the software renderer's (QPainter) antialiasing method is closer to to this one.

Log in to reply