c++ - 为什么QPainter::drawPoint画一条水平线段?

标签 c++ qt qpainter

我正在尝试使用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");
}

这是生成图像的左上角:

line instead of a point

我期望得到一个红色圆圈的点,或者至少是一个正方形 - 但我得到的是这条线段。如果我注释掉 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/

相关文章:

c++ - 用于发送电子邮件的命令行 C++ 程序

c++ - 使用预处理器反转数组

c++ - 为什么 QWebFrame::evalutateJavaScript 在这种情况下什么都不做?

c++ - 绘制圆弧并覆盖boundingRect()、shape()

python - 画家在另一个矩形内绘制圆角矩形

c++ - 我正在制作一个刽子手游戏,我需要帮助来弄清楚为什么它不能完全运行

c++ - 为什么 decltype 在这里工作,但不是 auto?

c++ - 如何在主线程外创建QtQuick窗口

c++ - Qt XML 读取元素并只获取根

python - 如何在Python中使用PyQt5绘制折线?