Reputation: 3192
I apologize if I give more details than necessary. I have a class Canvas
that looks like this:
class Canvas : public QWidget
{
Q_OBJECT
public:
explicit Canvas(int width = 700, int height = 700, QWidget *parent = 0);
void setDelegate(CanvasDelegate *delegate);
private:
CanvasDelegate *delegate;
void paintEvent(QPaintEvent *event);
void resizeEvent(QResizeEvent *resizeEvent);
[...]
};
The Canvas::paintEvent(QPaintEvent *)
function is implemented like this:
void Canvas::paintEvent(QPaintEvent *)
{
delegate->redrawBuffer();
QPainter canvas_painter(this);
canvas_painter.drawImage(0, 0, *(delegate->getImage()));
}
And so the class CanvasDelegate
looks like this:
class CanvasDelegate
{
friend class Canvas;
public:
CanvasDelegate(const Canvas *canvas);
~CanvasDelegate();
const QImage * getImage() const;
void drawPoint(const Complex &z, const QColor &color = "black", int width = 3);
[...]
virtual void redrawBuffer(const H2Isometry &mobius = H2Isometry::identity()) = 0;
virtual void mousePress(QMouseEvent * mouseEvent) = 0;
[...]
protected:
const Canvas *canvas;
int sizeX, sizeY;
[...]
QPen *pen;
QImage *image;
QPainter *painter;
void rescale(int sizeX, int sizeY);
};
The constructor of CanvasDelegate is as follows:
CanvasDelegate::CanvasDelegate(const Canvas *canvas) : canvas(canvas)
{
pen = new QPen;
image = new QImage(canvas->width(), canvas->height(), QImage::Format_RGB32);
painter = new QPainter(image);
[...]
}
I'm not sure this is the best design ever but this is not my question (any comments are welcome, though). My problem is what happens when the window (Canvas
) is resized. Here is what my code looks like:
void Canvas::resizeEvent(QResizeEvent *resizeEvent)
{
QSize newSize = resizeEvent->size();
delegate->rescale(newSize.width(), newSize.height());
//update();
}
void CanvasDelegate::rescale(int sizeX, int sizeY)
{
*image = QImage(sizeX, sizeY, QImage::Format_RGB32);
painter->eraseRect(0, 0, sizeX, sizeY);
this->sizeX = sizeX;
this->sizeY = sizeY;
[...]
}
The problem is that when I run the program, it crashes. Apparently there is a segmentation fault when painter->eraseRect(0, 0, sizeX, sizeY);
is called in void CanvasDelegate::rescale(int sizeX, int sizeY)
. I don't understand why, I don't see what the problem is.
In a previous version, I had written the following (which now seems to me more complicated than necessary):
void CanvasDelegate::rescale(int sizeX, int sizeY)
{
QImage * oldImage = image;
QImage * newImage = new QImage(sizeX, sizeY, QImage::Format_RGB32);
QPainter * oldPainter = painter;
QPainter * newPainter = new QPainter(newImage);
newPainter->eraseRect(0, 0, sizeX, sizeY);
newPainter->setPen(*pen);
image = newImage;
painter = newPainter;
delete oldImage;
delete oldPainter;
this->sizeX = sizeX;
this->sizeY = sizeY;
[...]
}
But that does not work: I get a Qt error QPaintDevice: Cannot destroy paint device that is being painted. If I remove delete oldImage;
and delete oldPainter;
, everything works fine but that is a disgusting memory leak, isn't it.
Does someone understand why what I have written does not work, and what I need to do?
Thank you very much for your attention.
Upvotes: 2
Views: 3469
Reputation: 7748
I'm not exactly sure why painter->eraseRect(0, 0, sizeX, sizeY);
segfaults, but it may be that when the paintdevice of a QPainter is an image, its size shoudn't change, and therefore *image = QImage(sizeX, sizeY, QImage::Format_RGB32);
breaks this assumption.
Therefore, I would try, before resizing the image, to delete the QPainter, then resize the image, then allocate a new QPainter. In code:
void CanvasDelegate::rescale(int sizeX, int sizeY)
{
delete painter;
*image = QImage(sizeX, sizeY, QImage::Format_RGB32);
painter = new QPainter(image);
painter->eraseRect(0, 0, sizeX, sizeY);
painter->setPen(*pen);
this->sizeX = sizeX;
this->sizeY = sizeY;
[...]
}
Upvotes: 1