George
George

Reputation: 630

Color merge problem upon drawing ellipses above lines in Qt

I'm developing a small painter-like application. I'd like my application to have a feature which would allow user to draw points and then connect them with lines in the order in which the points were drawn. I also want my points to be drawn above the lines. Here's how i'm trying to achieve this:

 void ImageViewer::on_linesAct_triggered()
{
    QPainter paint(objectpix);
    QPen LinePen (QColor(255-pointcolor[currentset-1].red(),255-pointcolor[currentset-1].green(),255-pointcolor[currentset-1].blue()));
    LinePen.setWidth(5);

    for(int i=0;i<count[currentset-1]-1;i++)
    {
        paint.setPen(LinePen);
        QPoint p1(static_cast<int>(round(tableX[i][currentset-1])),static_cast<int>(round(tableY[i][currentset-1])));
        QPoint p2(static_cast<int>(round(tableX[i+1][currentset-1])), static_cast<int>(round(tableY[i+1][currentset-1])));
        paint.drawLine(p1,p2);
        paint.setPen(QPen(pointcolor[currentset-1]));
        paint.setBrush(QBrush(pointcolor[currentset-1],Qt::SolidPattern));
        paint.drawEllipse(p1,2,2);
        paint.drawEllipse(p2,2,2);
    }

    /...
}

It works as intended except the fact that colors of lines and points kinda merge(not sure on nomenclature) together. The picture down below llustrates the problem. enter image description here Any idea on possible solution?

Upvotes: 1

Views: 227

Answers (2)

Dimitry Ernot
Dimitry Ernot

Reputation: 6594

If you consider the list of points [A, B, C, D] and your code:

  • Iteration 1: p1 = A, p2 = B

    • Draw line between A and B
    • Draw ellipse at A and B
  • Iteration 2: p1 = B, p2 = C

    • Draw line between B and C <-- Will draw above the ellipse at B
    • Draw ellipse at B and C <-- Will re-draw the ellipse at B
  • Iteration 3: p1 = C, p2 = D

    • Draw line between C and D <-- Will draw above the ellipse at C
    • Draw ellipse at C and D <-- Will re-draw the ellipse at C

You are drawing your ellipses twice with a the start of line between them. What you can see is the artifacts due to the aliasing (as mentionned in the other answer) and the first ellipse drawn below the second line.

The easiest way to achieve that is to use two loops:

class MyWidget: public QWidget
{
public:
    MyWidget(): QWidget()
    {}
    virtual void paintEvent(QPaintEvent* ev) override
    {
        QVector<QPoint> pointcolor;
        pointcolor << QPoint(10, 12) << QPoint(40, 60) << QPoint(70, 20) << QPoint(100, 100);
        QPainter paint(this);
        paint.setRenderHint(QPainter::Antialiasing);
        QPen LinePen (Qt::red);
        LinePen.setWidth(5);

        for(int i = 1;i != pointcolor.length();++i)
        {
            paint.setPen(LinePen);
            QPoint p1 = pointcolor.at(i - 1);
            QPoint p2 = pointcolor.at(i);
            paint.drawLine(p1,p2);
        }

        // Draw the points above the lines
        paint.setPen(Qt::green);
        paint.setBrush(Qt::green);
        for(QPoint const& point: pointcolor)
        {
            paint.drawEllipse(point,2,2);
        }
    }
};

Upvotes: 1

p-a-o-l-o
p-a-o-l-o

Reputation: 10057

I think you could try to set a rendering hint to the painter, using QPainter::setRenderHint, something like:

QPainter paint(objectpix);
paint.setRenderHint(QPainter::Antialiasing);

Upvotes: 1

Related Questions