我正在尝试使用QPainter::drawEllipse
绘制圆圈。我希望能够:
设置圆的笔触宽度(QPen::width
)
选择位于圆心(1x1
,1x2
,2x1
或2x2
)的像素的形状
(可选)使圆圈填充而不是描边
确保圆具有正确的半径(即使笔划宽度大于1时)
这些目标令人惊讶地难以实现。这是我要渲染(手工绘制)的示例:
图像为32x32(放大至512x512)。红色中心点位于(15,15)。中心是1x2
,因此中心像素下方有一个额外的红色像素。笔划的宽度为2像素。如果将笔划变宽,则像素将添加到圆的内部。无论笔划宽度如何,圆的边界框都是相同的。半径为8像素。每条蓝线长8像素。为了清楚起见,红色和蓝色像素仅用于描述该圆圈。它们不是我想要的输出的一部分。
我的问题真正归结为渲染一个完全适合矩形的椭圆。我可以使用中心点,半径和中心形状来计算矩形。这部分很容易。仅使用此矩形调用drawEllipse
无效。我认为我必须在调用drawEllipse
之前以某种方式调整此矩形,但是我不太确定如何调整它。我尝试摆弄它,发现了一些适用于某些笔宽而不适用于其他笔宽的解决方案。
笔帽重要吗?我一直在使用RoundCap
。我应该使用其他上限吗?
我快要考虑自己进行像素处理了。我正在渲染到QImage
并使用Source
复合操作,因此我的代码可能比drawEllipse
快一点。 memset
的速度大约是QImage::fill
的10倍,因此编写更快的代码可能不会太难!我宁可不必这样做。
最佳答案
我偶然发现了一个section in the docs,它讨论了QRect
的呈现方式。它描述了渲染像素与逻辑矩形之间的关系。渲染的矩形大于逻辑矩形。我要做的就是使逻辑矩形变小以进行补偿。
QRect adjustStrokedRect(const QRect rect, const int thickness) {
return QRect{
rect.left() + thickness / 2,
rect.top() + thickness / 2,
rect.width() - thickness,
rect.height() - thickness
};
}
好的,现在我可以将描边矩形渲染到正确的位置。椭圆由
QRect
描述,如果我仅将此变换应用于该矩形怎么办?不。
如果厚度为
1, 2, 4, 6
而不是3, 5, 7
,则可以正常工作。当厚度为3, 5, 7
时,圆圈太小一个像素。因此,我尝试在1
的矩形大小中添加thickness % 2 == 1 && thickness != 1
,但是从正方形渲染了一个不对称的圆。对于位置和大小的某些组合,即使大小为正方形,也会呈现不规则的不对称圆形。这是您可以轻松复制的怪异图像:
使用以下代码生成它:
QImage image{32, 32, QImage::Format_ARGB32_Premultiplied};
QPainter painter{&image};
QPen pen{Qt::NoBrush, 3.0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin};
pen.setColor(QColor{0, 255, 0, 255});
painter.setPen(pen);
painter.drawEllipse(8, 8, 17, 17);
image.save("weird.png");
我根本不知道那怎么可能。在我看来,
drawEllipse
正在渲染一个大致适合矩形的椭圆。我无法在文档中的任何地方找到矩形和椭圆之间的关系。也许是因为这是一个非常松散的关系。我毫不费力地使
QPainter::drawEllipse
绘制笔划宽度为1
的圆,所以现在我只允许我的应用程序中不使用粗圆。如果无法完美渲染,则完全不会渲染。我并未将此答案标记为已接受,尽管我仍希望此方法有效。关于c++ - 使用Qt绘制像素完美的圆,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54776781/