我正在尝试使用QPainter
绘制一个3像素的大点。但下面的代码却绘制了一条宽度为 3 像素的水平线。
#include <QPainter>
#include <QImage>
int main()
{
const int w=1000, h=1000;
QImage img(w, h, QImage::Format_RGBX8888);
{
QPainter p(&img);
p.fillRect(0,0,w,h,Qt::black);
p.scale(w,h);
p.setPen(QPen(Qt::red, 3./w, Qt::SolidLine, Qt::RoundCap));
p.drawPoint(QPointF(0.1,0.1));
}
img.save("test.png");
}
这是生成图像的左上角:
我期望得到一个红色圆圈的点,或者至少是一个正方形 - 但我得到的是这条线段。如果我注释掉 p.scale(w,h)
并在位置处绘制宽度为 3
(而不是 3./w
)的点(100,100)
,然后我得到一个高度和宽度基本对称的小 3 像素点。
发生什么事了?为什么我得到的是线段而不是预期的点?以及如何修复它,而不求助于绘制椭圆或避免 QPainter::scale
?
我在 Linux x86 上使用 Qt 5.10.0 和 g++ 5.5.0。 Qt 5.5.1 上也会发生同样的情况。
最佳答案
看来QPaintEngineEx::drawPoints
将点渲染为长度为 1/63.
的线段。请参阅 qtbase/src/gui/painting/qpaintengineex.cpp 中的以下代码在 Qt 源代码中:
void QPaintEngineEx::drawPoints(const QPointF *points, int pointCount)
{
QPen pen = state()->pen;
if (pen.capStyle() == Qt::FlatCap)
pen.setCapStyle(Qt::SquareCap);
if (pen.brush().isOpaque()) {
while (pointCount > 0) {
int count = qMin(pointCount, 16);
qreal pts[64];
int oset = -1;
for (int i=0; i<count; ++i) {
pts[++oset] = points[i].x();
pts[++oset] = points[i].y();
pts[++oset] = points[i].x() + 1/63.;
pts[++oset] = points[i].y();
}
QVectorPath path(pts, count * 2, qpaintengineex_line_types_16, QVectorPath::LinesHint);
stroke(path, pen);
pointCount -= 16;
points += 16;
}
} else {
for (int i=0; i<pointCount; ++i) {
qreal pts[] = { points[i].x(), points[i].y(), points[i].x() + qreal(1/63.), points[i].y() };
QVectorPath path(pts, 2, 0);
stroke(path, pen);
}
}
}
注意 pts[++oset] = points[i].x() + 1/63.;
不透明画笔分支中的线。这是路径的第二个顶点 - 相对于该点的所需位置进行了移动。
这解释了为什么该线延伸到所请求位置的右侧以及为什么它取决于比例。所以,对于理想的QPainter
来说,OP中的代码似乎并没有错。实现,但刚刚遇到了 Qt 错误(无论是在方法的实现中还是在其文档中)。
因此结论:必须通过使用不同的比例、绘制椭圆或绘制长度比 QPainter::drawPoints
小得多的线段来解决这个问题。确实如此。
我已将此报告为 QTBUG-70409 .
关于c++ - 为什么QPainter::drawPoint画一条水平线段?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52194141/