前言
前段时间遇到这样一个问题,使用QPainter绘制直线的时候,设置了笔宽为1像素,但是绘制出来的线条却是2px宽度,而且设置的画笔颜色很明显是降低了透明度,不是最“纯正”的颜色。
当时就感觉非常奇怪,明明设置的画笔宽度是正常的,为啥绘制出来不是自己想要的样子。而且,当画笔宽度设置为2px后,发现结果又是正常的,透明度也是正常。
后来一句句的代码排查问题才发现了其中的猫腻。
先来看看这个现象,为了演示效果,分别绘制了1px和2px时是的直线和矩形:
上面是1px效果,下面是2px效果,颜色设置都是一样的,可以很明显的看到上面绘制的图形效果也是2px,而且透明度降低了。
ok,带着问题,进入今天的主题。
正文
先说结论,为什么会导致上面的现象。
是因为设置了painter渲染器,painter.setRenderHint(QPainter::Antialiasing,true);
为了验证和对比效果,绘制了四组图形,分别是1px和2px,然后设置了渲染器和不设置渲染器。
上代码:
void Widget::paintEvent(QPaintEvent *e)
{
QPainter painter(this);
painter.fillRect(this->rect(),Qt::black);
painter.setBrush(Qt::NoBrush);
QPen pen;
pen.setColor(Qt::red);
pen.setWidth(1);
painter.setPen(pen);
painter.setRenderHint(QPainter::Antialiasing,true);
painter.drawLine(100,50,100,150);
painter.drawRect(130,50,100,100);
painter.drawRoundedRect(260,50,110,100,20,20);
painter.setRenderHint(QPainter::Antialiasing,false);
painter.drawLine(400,50,400,150);
painter.drawRect(430,50,100,100);
painter.drawRoundedRect(560,50,110,100,20,20);
pen.setWidth(2);
painter.setPen(pen);
painter.setRenderHint(QPainter::Antialiasing,true);
painter.drawLine(100,200,100,300);
painter.drawRect(130,200,100,100);
painter.drawRoundedRect(260,200,110,100,20,20);
painter.setRenderHint(QPainter::Antialiasing,false);
painter.drawLine(400,200,400,300);
painter.drawRect(430,200,100,100);
painter.drawRoundedRect(560,200,110,100,20,20);
QWidget::paintEvent(e);
}
看效果:
上面一排是1px,下面一排是2px,左边是设置了RenderHint
,右边没有设置。
可以看出来设置渲染器后绘制的圆角更加平滑,而没有设置的情况 圆角会带有“毛刺”,当我们需要绘制曲线或者这种类似的有弧度的图形时,添加渲染器设置会让绘制效果更加平滑一些,
而RenderHint的设置包含了很多种,分别对应不同的场景,具体可以查看Qt帮助文档。
回到最开始的话题,为啥设置了渲染器后绘制1px的图形会出现上面那种情况。
猜测的原因应该是:设置painter.setRenderHint(QPainter::Antialiasing,true);
后,绘制曲线或者类似的有弧度的图形时,会将去弧度变成更加平滑,那在源码内部实现平滑效果时,应该是在图形边缘补充了一个像素的绘制,同时降低其透明度,使其锯齿处显得更加平滑,这样就可以解释为什么只绘制1px宽度时会出现看到2px宽度的效果。
so,当我们只需要绘制直线或者矩形或者不带圆角和弧度的图形时,其实不需要设置渲染器效果,这样在绘制1px宽度的情况下能保持想要的效果~