Search code examples
c++qtqpainterqpen

How to draw over an existing dotted line with a wider one?


I want to draw over an existing dotted line (left black) with a boulder line (right green) to simulate selection effect,
but the strokes of a bolder line are not aligned with the original one
even though they are painted using the same start/end points p1 and p2: enter image description here

Here's the code:

const QPointF p1{};
const QPointF p2{};

// draw thin black line
QPen blackPen;
blackPen.setWidth(10);
blackPen.setColor(Qt::black);
blackPen.setStyle(Qt::DotLine);

painter->setPen(blackPen);
painter->setBrush(Qt::NoBrush);
painter->drawLine(p1, p2);

// draw bold green line using the same points
QPen boldGreenPen;
boldGreenPen.setWidth(12);
boldGreenPen.setColor(Qt::green);
boldGreenPen.setStyle(Qt::DotLine);

painter->setPen(boldGreenPen);
painter->setBrush(Qt::NoBrush);
painter->drawLine(p1, p2);

Is it possible to achieve the desired behavior?


Solution

  • According to Qt docs:

    The dash pattern is specified in units of the pens width

    Which means we'd have to calculate ratio between width of both lines like this:

    QPen pen;
    const double penWidth(pen.widthF());
    const auto penDashPattern(pen.dashPattern());
    
    QPen boldPen(pen);
    const double boldPenWidth(penWidth + 2);
    auto boldPenDashPattern(boldPen.dashPattern());
    
    const double ratio(penWidth / boldPenWidth);
    for (auto & pattern : boldPenDashPattern)
    {
        pattern *= ratio;
    }
    
    boldPen.setWidthF(boldPenWidth);
    boldPen.setDashPattern(boldPenDashPattern);
    
    painter->setPen(boldPen);
    

    Which gives us a desired result