Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

QPainter keep previous drawings

Tags:

c++

qt

qpainter

This is my first time using Qt and I have to make a MSPaint equivalent with Qt. I am however having trouble with painting my lines. I can currently draw a line by clicking somewhere on the screen and releasing somewhere else, however when I draw a second line the previous line is erased. How could I keep the previously painted items when painting another item?

void Canvas::paintEvent(QPaintEvent *pe){
    QWidget::paintEvent(pe);
    QPainter p(this);
    p.drawPicture(0,0,pic);
}

void Canvas::mousePressEvent(QMouseEvent *mp){
    start = mp->pos();
}

void Canvas::mouseReleaseEvent(QMouseEvent *mr){
    end = mr->pos();
    addline();
}

void Canvas::addline()Q_DECL_OVERRIDE{
    QPainter p(&pic);
    p.drawLine(start,end);
    p.end();
    this->update();
}

Canvas is a class that derives QWidget, it has 2 QPoint attributes start and end.

Class body:

class Canvas : public QWidget{
Q_OBJECT
private:
    QPoint start;
    QPoint end;
    QPicture pic;
public:
    Canvas(){paint = false;setAttribute(Qt::WA_StaticContents);}
    void addline();
protected:
    void paintEvent(QPaintEvent *);
    void  mousePressEvent( QMouseEvent * );
    //void  mouseMoveEvent( QMouseEvent * );
    void  mouseReleaseEvent( QMouseEvent * );

};
like image 718
anaBad Avatar asked Oct 04 '15 13:10

anaBad


1 Answers

QPicture records QPainter commands. Also from its documentation you can read this:

Note that the list of painter commands is reset on each call to the QPainter::begin() function.

And the QPainter constructor with a paint device does call begin(). So each time the old recorded commands are deleted.

It may sound tempting to use it, since it does say a few good things, for example, that it is resolution independent, but this is not how drawing applications work in reality. Switch to a QPixmap and your drawings will persist.

Also, don't forget to initialize the pixmap, because by default it will be empty and you will not be able to draw on it.

Canvas() : pic(width,height) {...}

Furthermore, if you would like the introduce the concept of brushes as in artistic brushes and not QBrush, you might want to look at this approach to draw the line.

EDIT: Note that you should be able to prevent QPicture from losing its content by not calling begin() on it more than once. If you create a painter, dedicated to only drawing on it at class scope, and call begin in the constructor, different recorded drawing operations should persist. But as their number increases it will take more and more time to draw the QPicture to your widget. You could come around that by using both a QPicture and a QPixmap, and draw to both, use the picture to record the actions and the pixmap to avoid continuously redrawing the picture, even though you will do double the work it will still be more efficient, while you still retain the possibility to use the picture to re-rasterize in a different resolution or save the drawing history. But I doubt QPicture will do well as your drawing application begins to take shape of an actual drawing application, for example when you start using pixmap brushe stencils and such.

like image 103
dtech Avatar answered Nov 16 '22 12:11

dtech