Jarra McIntyre
Jarra McIntyre

Reputation: 1285

QPainter drawLines method

I use the following code to draw the axes of a graph in qt:

...

static const std::array<const QPointF,10*2> horizontalAxis = {
    QPointF(0.f,0.f), QPointF(1.f,0.f),
    // Horizontal scales
    QPointF(0.f,0.f), QPointF(0.f,1.f),
    QPointF(0.125f,0.f), QPointF(0.125f,1.f),
    QPointF(0.25f,0.f), QPointF(0.25f,1.f),
    QPointF(0.375f,0.f), QPointF(0.375f,1.f),
    QPointF(0.5f,0.f), QPointF(0.5f,1.f),
    QPointF(0.625f,0.f), QPointF(0.625f,1.f),
    QPointF(0.75f,0.f), QPointF(0.75f,1.f),
    QPointF(0.875f,0.f), QPointF(0.875f,1.f),
    QPointF(1.f,0.f), QPointF(1.f,1.f)
};

static const std::array<const QPointF,6*2> verticalAxis = {
    QPointF(0.f,0.f), QPointF(0.f,1.f),
    // Vertical scales
    QPointF(0.f,0.f), QPointF(-1.f,0.f),
    QPointF(0.f,0.25f), QPointF(-1.f,0.25f),
    QPointF(0.f,0.5f), QPointF(-1.f,0.5f),
    QPointF(0.f,0.75f), QPointF(-1.f,0.75f),
    QPointF(0.f,1.f), QPointF(-1.f,1.f)
};

...

void Plot::paint(QPainter& p)
{
    int const width = p.device()->width();
    int const height = p.device()->height();
    Q_ASSERT(width > xpaddingLeft + xpaddingRight);
    Q_ASSERT(height > ypaddingTop + ypaddingBottom);

    if(dirty) {
        recalculate();
    }

    p.save();

    int const bottomLeftX = xpaddingLeft;
    int const bottomLeftY = height - ypaddingBottom;
    int const scaleX = width - xpaddingLeft - xpaddingRight;
    int const scaleY = height - ypaddingTop - ypaddingBottom;

    p.setRenderHint(QPainter::HighQualityAntialiasing,false);
    p.setRenderHint(QPainter::Antialiasing,false);

    QPen pen(QBrush(QColor::fromRgb(0,0,0)), 2);
    pen.setCosmetic(true);  // Do not apply scale to the pen
    p.setPen(pen);

    // Horizontal Axis
    p.resetTransform();
    p.translate(bottomLeftX,bottomLeftY);   // Origin at bottom left
    p.scale(scaleX,scaleSize); // y-axis points down. Only scale y to match the scale-mark size
    p.drawLines(&horizontalAxis[0], (int)horizontalAxis.size());

    // Vertical Axis
    p.resetTransform();
    p.translate(bottomLeftX,bottomLeftY);
    p.scale(scaleSize,-scaleY); // y-axis points up. Only scale x to match the scale-mark size
    p.drawLines(&verticalAxis[0], (int)verticalAxis.size());

    ...
}

This results in a graph like the following, with a weird artifact to the lhs (showing just the axes with no data loaded):
Horizontal axis scales result in weird artifact to the LHS Horizontal axis scales result in weird artifact to the LHS

Commenting out all of the QPointF definitions for the horizontal scale definition removes this weird artifact. However commenting any individual pair of points doesn't seem to affect it. If I switch from using the drawLines() method, as follows, the stretching disappears.

    //p.drawLines(&horizontalAxis[0], (int)horizontalAxis.size());
    for(size_t k = 0; k < horizontalAxis.size()-1; k += 2) p.drawLine(horizontalAxis[k],horizontalAxis[k+1]);

And I get a result like the following without any artifacts (Showing just the axes with no data loaded):
Horizontal axes scales show no switching Horizontal axes scales show no switching

Am I missing something or is this a bug in drawLines()?

I use the drawLines() function twice more to draw the vertical axis and actual data (as a line graph) without (apparent) issue but I want to be more certain that it won't result in odd artifacts in circumstances I haven't managed to test for.

Upvotes: 0

Views: 1928

Answers (1)

ThorngardSO
ThorngardSO

Reputation: 1211

The drawLines() overload you are using is (from the Qt5 docs):

QPainter::drawLines (const QPointF* pointPairs, int lineCount)

May I draw your attention to the second parameter. It's called lineCount, not point-count, so you have to pass HALF the number of points:

assert (0 == horizontalAxis.size () % 2);
p.drawLines (&horizontalAxis[0], static_cast<int> (horizontalAxis.size () / 2));

Upvotes: 1

Related Questions