Unsolved 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 if(tilt()) { buffer += 1; } //start 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); setAntialiasing(true); QBrush brush(QColor("#53b748")); painter->setBrush(brush); painter->setPen(Qt::NoPen); painter->setRenderHint(QPainter::Antialiasing, true); painter->drawPath(path);
Is there a fix for this? A better way to implement what I want? I'm open to any and all suggestions.
-
@zhannum
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
-
I only want to rotate 5 degrees. I want to rotate when the item is dragged, so I have:
rotation: Drag.active ? 5 : 0
-
@zhannum
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
-
@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. -
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.
-
@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?
https://doc.qt.io/qt-5/qtquick-visualcanvas-scenegraph-renderer.html#antialiasingso you might want to try
msaa
. I assume the software renderer's (QPainter) antialiasing method is closer to to this one.