Draw a line and curves with fading edges with QPainter


QPainter is very easy to use and to draw a line one would simply do this:

QPainter painter(&image);
QPen pen;
pen.setWidth(5);
pen.setColor("black");
painter.setPen(pen);
painter.drawLine(QPointF(0,0), QPointF(200,250));

Now this works well, but I would like to create a "special" pen that produce lines with "smoothed" edges. For example, suppose the line I want to draw has a thickness of 10 pixels, then I would like the middle of the line (by middle I mean in terms of thickness and not length) to be fully opaque and at the edges the line should become semitransparent. I believe this could be obtained for example having the picture below as my point and then "drag" and paint the line so I will obtain the effect I desire. I know that Qt provides you with QBrush and gradients, but I can't figure out how to to do this.

Pic


Answers:


While Qt definitely has many drawing functions, there is none to let you draw using a pixmap brush along a path like you describe.

I can think of 2 ways to achieve what you want:

  1. Draw the path using standard non-fuzzy brush multiple times with a varying brush width and a transparent color. With enough iterations this will approximate the "fuzzy line" you are looking for.

  2. Draw the pixmap repeatedly along the path. This is usually how drawing software like photoshop or gimp will do it as it allows for some flexibility in the parameters such as different brush pixmaps and orientations etc.

I will try to provide example code (untested for now as I am currently away from my dev computer) for the second way of doing it here:

void drawPathWithPixmapBrush(QPainter painter, QPainterPath path, QPixmap pixmapBrush, qreal spacing=1.0) {
    qreal length = path.length();
    qreal pos = 0.0;
    // Adjust the spacing to be relative to brush size
    spacing=(spacing * pixmapBrush.width() );
    while (pos < length) {
        qreal percent = path.percentAtLength(pos);
painter.drawPixmap(path.pointAtPercent(percent), pixmapBrush);
pos += spacing;
    }
}

As you can see, this code will iteratively move along the given QPainterPath, and for each step draw the QPixmap brush to the given QPainter, resulting in what can be preceived as one continuous line drawn along the path with the pixmap brush.

QPainterPath supports all drawing operations that QPainter does, such as polygons, splines, lines, arches etc., so it will function as a dropin replacement for your existing QPainter draw calls for the most part (see the full list of drawing operations).

Here is example code to construct a simple straight line segment using QPainterPath:

QPainterPath path
QPointF lastPosition(10, 10);
QPointF currentPosition(100, 100);
path.moveTo(lastPosition);
path.lineTo(currentPosition);

Possible improvements include calculating spacing so that it ends exactly on the end of the line, and also maybe more correctly calculating the required number of draws will best give the impression of a line.