2

如果我提供了不必要的详细信息,我深表歉意。我有一个Canvas看起来像这样的类:

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);
    [...]
};

Canvas::paintEvent(QPaintEvent *)功能是这样实现的:

void Canvas::paintEvent(QPaintEvent *)
{
    delegate->redrawBuffer();
    QPainter canvas_painter(this);
    canvas_painter.drawImage(0, 0, *(delegate->getImage()));
}

所以这个类CanvasDelegate看起来像这样:

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);
};

CanvasDelegate 的构造函数如下:

CanvasDelegate::CanvasDelegate(const Canvas *canvas) : canvas(canvas)
{
    pen = new QPen;
    image = new QImage(canvas->width(), canvas->height(), QImage::Format_RGB32);
    painter = new QPainter(image);
    [...]
}

我不确定这是有史以来最好的设计,但这不是我的问题(尽管欢迎任何评论)。Canvas我的问题是调整窗口 ( ) 大小时会发生什么。这是我的代码的样子:

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;
    [...]
}

问题是当我运行程序时,它崩溃了。显然在painter->eraseRect(0, 0, sizeX, sizeY);调用时存在分段错误void CanvasDelegate::rescale(int sizeX, int sizeY)。我不明白为什么,我不明白问题是什么。

在以前的版本中,我编写了以下内容(现在在我看来,这比必要的更复杂):

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;
    [...]
}

但这不起作用:我收到 Qt 错误QPaintDevice: Cannot destroy paint device that is beingpainting。如果我删除delete oldImage;and delete oldPainter;,一切正常,但这是一个令人作呕的内存泄漏,不是吗。

有人明白为什么我写的东西不起作用,我需要做什么吗?

非常感谢您的关注。

4

1 回答 1

1

我不确定为什么painter->eraseRect(0, 0, sizeX, sizeY);会出现段错误,但可能是当 QPainter 的paintdevice 是图像时,它的大小不应该改变,因此*image = QImage(sizeX, sizeY, QImage::Format_RGB32);打破了这个假设。

因此,我会在调整图像大小之前尝试删除 QPainter,然后调整图像大小,然后分配一个新的 QPainter。在代码中:

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;
    [...]
}
于 2014-10-04T22:00:54.643 回答