QRectF与QRect的right()/bottom()方法行为差异及绘图适配咨询
一、为什么QRectF和QRect的right()/bottom()行为不同?
这个差异其实是Qt针对两种矩形的定位场景设计不同导致的:
QRect是面向像素的整数矩形:它的坐标体系是**包含性(inclusive)**的,
right()返回的是矩形最后一个包含的像素的x坐标。比如你创建的QRect r2(0, 0, 20, 20),宽度是20,意味着它覆盖从x=0到x=19的20个像素,所以right()计算为left() + width() - 1,也就是0+20-1=19。而width()直接返回构造时的宽度值20,和视觉上的像素数量完全匹配。QRectF是面向几何计算的浮点矩形:它的坐标体系是**排他性(exclusive)**的,
right()返回的是矩形的右边界x值,而非最后一个包含点的坐标。所以QRectF r1(0, 0, 20, 20)的right()就是left() + width(),也就是0+20=20,这符合数学上矩形边界的定义(矩形内部是[left, right) × [top, bottom)的区间)。它的width()同样返回构造时的20,因为width() = right() - left(),和数学逻辑完全一致。
简单来说,QRect服务于像素绘制的精确覆盖,QRectF服务于几何空间的精确计算,两者的设计目标不同,才导致了这个API差异。
二、QGraphicsItem中绘制无抗锯齿1像素线条的处理方法
当你用QRectF绘制1像素宽度的无抗锯齿线条时,直接使用原始矩形会出现模糊问题——因为QRectF的边界是浮点坐标,默认情况下绘制的线条中心会落在整数坐标上,导致线条覆盖半个像素到相邻区域,即使关闭抗锯齿也会有边缘失真。
你提到的boundingRect().adjust(0,0,-1,-1)是一种非常可行的解决方案:调整后的矩形右边界和下边界从原来的right()/bottom()变成了right()-1/bottom()-1,这样矩形的边缘刚好对齐到像素的整数边界上,绘制的1像素线条会完全覆盖目标像素,不会产生模糊。
另外还有两种补充方案可以参考:
- 关闭抗锯齿并对齐坐标:在绘制前调用
painter->setRenderHint(QPainter::Antialiasing, false),同时确保矩形的坐标是整数(比如将QRectF转换为QRect,或者手动调整坐标到整数)。 - 使用Cosmetic Pen:如果需要线条在缩放时保持1像素宽度,可以设置
QPen pen; pen.setCosmetic(true);,但同样需要确保矩形边界对齐像素,否则仍可能出现模糊。
不过最稳妥的方式还是针对无抗锯齿的1像素线条,将QRectF调整为adjust(0,0,-1,-1),让矩形的边界符合QRect的像素包含逻辑,这样绘制出来的线条会清晰锐利。
内容的提问来源于stack exchange,提问作者Ludek Vodicka

