C++/Qt:改变正在绘制的Q图像的大小

C++/Qt : change (the size of) a QImage that is being painted

本文关键字:图像 绘制 Qt 改变 C++      更新时间:2023-10-16

如果我提供了超出必要的详细信息,我深表歉意。我有一个类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;
    [...]
}

问题是,当我运行程序时,它会崩溃。显然,在void CanvasDelegate::rescale(int sizeX, int sizeY)中调用painter->eraseRect(0, 0, sizeX, 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:无法破坏正在绘制的绘制设备。如果我删除delete oldImage;delete oldPainter;,一切都很好,但这是一个令人恶心的内存泄漏,不是吗?

有人理解为什么我写的东西不起作用,以及我需要做什么吗?

非常感谢您的关注。

我不太清楚painter->eraseRect(0, 0, sizeX, sizeY);为什么会出错,但可能是因为当QPainter的绘画设备是图像时,它的大小不应该改变,因此*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;
    [...]
}