Search code examples
c++qtqpen

Multicolored dashed line with a dashed pattern using QPen


I need to draw a multicoloured line with QPen that may consist of up to three colours within a dashed pattern.

Different colours should be on one line.

Any suggestions on how I can achieve it?

Thank you.


Solution

  • Developing the idea of @goug, you can do something like:

    void drawWithManualDashedLine(QPainter& painter, const QLine& line) {
      const int scale = 10;
    
      QPen pen;
      pen.setWidth(3);
    
      pen.setColor(Qt::red);
      pen.setDashPattern({ 0.0, 1.0 * scale, 1.0 * scale, 7.0 * scale });
      painter.setPen(pen);
      painter.drawLine(line);
    
      pen.setColor(Qt::green);
      pen.setDashPattern({ 0.0, 4.0 * scale, 1.0 * scale, 4.0 * scale});
      painter.setPen(pen);
      painter.drawLine(line);
    
      pen.setColor(Qt::blue);
      pen.setDashPattern({ 0.0, 7.0 * scale, 1.0 * scale, 1.0 *scale });
      painter.setPen(pen);
      painter.drawLine(line);    
    }
    

    Now, a more generic solution for n colors (I know it has too many parameters, it's just an idea). The trick is done creating a single dash-pattern, and moving it using QPen::setDashOffset for each color:

    void drawMultiColorDashedLine(QPainter& painter, const QLine& line,
        int length, int gap, int width,
        const QList<QColor>& colors, bool startWithGap = false) {
      const int n = colors.count();
      const int initialGap = startWithGap ? gap : 0;
    
      QPen pen;
      pen.setWidth(width);
      pen.setDashPattern({ (qreal)length, (qreal)(gap * n + length * (n - 1)) });
      for (int ii = 0; ii < n; ++ii) {
        pen.setColor(colors[ii]);
        pen.setDashOffset(-ii * (length + gap) - initialGap);
        painter.setPen(pen);
        painter.drawLine(line);
      }
    }
    

    So they can be called:

    void Widget::paintEvent(QPaintEvent*)
    {
      QPainter painter(this);
    
      const QLine line1(0, height() / 3, width(), height() / 3);
      drawMultiColorDashedLine(painter, line1, 10, 20, 3, { Qt::blue, Qt::yellow }, true);
    
      const QLine line2(0, height() / 2, width(), height() / 2);
      drawWithManualDashedLine(painter, line2);
    
      const QLine line3(0, 2 * height() / 3, width(), 2 * height() / 3);
      drawMultiColorDashedLine(painter, line3, 10, 20, 3, { Qt::red, Qt::black, Qt::blue, Qt::magenta }, false);
    }
    

    enter image description here

    The full working example is available at GitHub