I have written a small test script in Python and PySide6 to test the vector graphics capabilities of Qt, in particular the accuracy when it comes to the exact shapes and positions of the drawn figures. My first test was to draw a disk with a slightly smaller disk within it:
import sys
from PySide6.QtCore import Qt, QPoint
from PySide6.QtWidgets import QApplication, QWidget
from PySide6.QtGui import QPainter, QBrush
radii_difference = 1
x_offset = 0
class MyWidget(QWidget):
def paintEvent(self, event):
self.setWindowTitle("radii_difference: {}; x_offset: {}".format(radii_difference, x_offset))
print("radii_difference: {}; x_offset: {}".format(radii_difference, x_offset))
painter = QPainter(self)
painter.setRenderHint(QPainter.Antialiasing, on=True)
painter.setPen(Qt.NoPen)
painter.setBrush(QBrush(Qt.red))
painter.drawEllipse(QPoint(300, 250), 200, 200)
painter.setBrush(QBrush(Qt.blue))
painter.drawEllipse(QPoint(300 + x_offset, 250), 200 - radii_difference, 200 - radii_difference)
if __name__ == '__main__':
app = QApplication(sys.argv)
widget = MyWidget()
widget.show()
sys.exit(app.exec_())
As can be seen in the code, I call the difference of the radii radii_difference
, and I also create another variable x_offset
to parameterize the position of the inner disk. When trying with two different values for radii_difference
ā0.5 and 1āI see no difference in the thickness of the red outline of the blue disk at all, which indicates that painter.drawEllipse
rounds down the rx
and ry
arguments to the closest integer.
Likewise, if I change x_offset
from 0
to 0.5
, PyCharm highlights 300 + x_offset
and gives me the mouse-over text "Expected type 'int', got 'float' instead
", indicating that QPoint
(and therefore also QPainter.drawEllipse
) only accepts integer (center point) coordinates, and when I run the application, I see no difference from the previous figure (in particular, if drawEllipse
would have supported non-integer center point coordinates, the red outline would have been about three times as thick on the left side than on the right side, but it instead appear equally thick everywhere).
Both of these discoveries makes it feel like QPainter
offers very limited accuracy of the positions and sizes of drawn objects (I guess this translates to other shapes as well, not only ellipses).
Is there some way to increase this accuracy somehow when using QPainter
? If not, is there some alternative way to draw vector graphics in Qt (especially with PySide6, but I might consider switching to C++ if that offers greater possibilities) that gives me subpixel accuracy of positions, shapes and sizes of drawn object?
I found the answer by looking at the method in the C++ API; there it exists in five different overloads, two of which can offer subpixel accuracy: void drawEllipse(const QRectF &rectangle)
and void drawEllipse(const QPointF ¢er, qreal rx, qreal ry)
I tested substituting QPointF
for QPoint
, and it solved the problem.