【问题标题】:C++/Qt : change (the size of) a QImage that is being paintedC++/Qt:更改正在绘制的 QImage (的大小)
【发布时间】:2014-10-04 21:50:21
【问题描述】:

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

我不确定这是有史以来最好的设计,但这不是我的问题(不过,欢迎任何 cmets)。我的问题是调整窗口 (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;,一切正常,但这是一个令人作呕的内存泄漏,不是吗。

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

非常感谢您的关注。

【问题讨论】:

    标签: c++ qt canvas resize paintevent


    【解决方案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;
        [...]
    }
    

    【讨论】:

    • @Seub 查看我的更新,我很少直接在图像上绘画,所以在这种情况下我的回答实际上是错误的。 :)
    • 好的,我正在阅读您编辑的答案。但是,您所建议的(或多或少)不是我在“以前的版本”中所写的吗?
    • @Seub 查看编辑。不完全是,在您的情况下,您调用image = newImage;,而oldPainter 仍然在image 上“绘画”(可能),即错误QPaintDevice:无法破坏正在绘画的绘画设备 .所以delete oldPainter;必须出现在image = newImage;之前。
    • @seub 或者实际上,简单地交换 delete oldImage;delete oldPainter; 应该可以。
    • 很好,您的解决方案有效!非常感谢!非常感谢。
    猜你喜欢
    • 2011-10-28
    • 1970-01-01
    • 2015-12-15
    • 1970-01-01
    • 2019-02-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-15
    相关资源
    最近更新 更多