在启用抗锯齿功能的 QPainter 上绘制线宽为 1px 的矩形时,无论设置什么 JoinStyle,都会导致角稍微透明。对于折线和 QPainterPaths 也可以观察到同样的情况
def paintEvent(self, event):
with QPainter(self) as p:
p.setRenderHint(QPainter.Antialiasing, True)
p.fillRect(self.rect(), QColor('black'))
p.setBrush(Qt.NoBrush)
# 1px width border, corner is partially transparent
p.setPen(QPen(QColor("orange"), 1, cap=Qt.SquareCap, join=Qt.MiterJoin))
p.drawRect(QRectF(10.5, 10.5, 50., 25.))
# 3px width border, corner is crisp
p.setPen(QPen(QColor("orange"), 3, cap=Qt.SquareCap, join=Qt.MiterJoin))
p.drawRect(QRectF(15.5, 15.5, 50., 25.))
产生以下输出:
有没有办法让 1px 宽的笔获得清晰的角,同时也适用于部分透明的线条和任意 QPainterPaths?
单独绘制每条线:
工作正常,但由于拐角处重叠,存在部分透明线条的伪像。
单独绘制每条线,但将每条线的开头移动 1:
解决了部分透明直线直角的问题,但不能解决其他角度或曲线的问题。
暂时禁用抗锯齿:
对角线和曲线变得锯齿状。
这是由私有 QCosmeticStroker 引起的,QPainter 在绘制画笔宽度在 0 到 1(含)之间的路径(在绘画设备比例中)时使用该私有 QCosmeticStroker。
在抗锯齿模式下绘制“像素完美”线条一直有点复杂,并且总是存在一定程度的妥协(以及可能的错误)。
同样,该描边器虽然通常准确、快速且高效,但在某些情况下可能会失败(要了解实际情况有多么复杂,请参阅其当前的实现),而人们会认为绘制一个简单的方角可能不会这可能是一个问题,在处理“多段线”(也可能包括曲线)和闭合路径的模块化绘制时可能会出现这个问题。
还要考虑到,对于 1 像素宽的笔,连接样式差异几乎可以忽略不计:默认的斜角连接将填充 87.5% 的像素区域,而圆形连接则约为 94.6%。
不过,它可能仍然值得报告错误。
在任何情况下,一个简单的解决方法是防止笔触发挥作用:只需使用略大于 1 的笔宽度。这可能会有点效率低下,因为画家需要检查是否即使对于直正交线,线也会超出“像素边界”,因此几乎没有必要尝试应用抗锯齿,但如果图像精度更重要,那么这是可以接受的成本:
# no need to set the cap, which already defaults to square
p.setPen(QPen(QColor("orange"), 1.0001))