【问题标题】:Avoid Qpainter memory leak避免 Qpainter 内存泄漏
【发布时间】:2018-04-08 09:47:54
【问题描述】:

我在 QPixmap 上使用 QPainter 时遇到了内存泄漏问题。我需要在地图(导航点)上围绕地球设置大约 250000 个点。它们中的每一个都共享相同的图标,但具有特定的标签。我将所有这些点添加到同一层。

这是我的代码:

void Gspv::addFixes() // waypoints layer
{
    waypoints = new GeometryLayer("Waypoints", mapadapter);
    mc->addLayer(waypoints);

    //Icon
    QPixmap icone(38,38);
    icone.fill(Qt::transparent);
    QPainter *paint = new QPainter(&icone);
    paint->setRenderHint(QPainter::Antialiasing);
    paint->setBrush(Qt::cyan);
    paint->setPen(Qt::black);
    static const QPoint triangle[3] = {
        QPoint(15,0),
        QPoint(3, 20),
        QPoint(27,20)
    };
    paint->drawPolygon(triangle, 3);
    delete paint;

    //Check file
    QFile file(QCoreApplication::applicationDirPath() + "/data/Waypoints.txt");
    if(!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
        QMessageBox::information(0, "erreur lecture fichier : " + file.fileName(), file.errorString());
        return;
    }

    //Parsing file
    QTextStream in(&file);
    while(!in.atEnd()) {
        QString line = in.readLine();
        QStringList fields = line.split(",");
        QString str = fields.at(1);
        double latitude = str.toDouble();
        str = fields.at(2);
        double longitude = str.toDouble();
        str = fields.at(0);

        addCode(icone,str); // Prob here

        //Add current point to layer
        Point* pointCourant = new Point(longitude, latitude, icone, str);
        pointCourant->setBaselevel(10);
        pointCourant->setMaxsize(QSize(38, 38));
        waypoints->addGeometry(pointCourant);

    }

    file.close();
}


//Add code to QPixmap
void Gspv::addCode(QPixmap &pm, QString &code)
{
    QPainter pmp(&pm);
    pmp.setPen(Qt::black);
    pmp.setFont(QFont("ArialBold",9));
    pmp.eraseRect(0,20,38,15);
    pmp.drawText(0,32,code);
}

一切都按预期工作,除了它会导致严重的内存泄漏。 问题是在 while 循环中添加代码时。无论我做什么(在 addfixes 方法中添加代码或在特定的 addCode 方法中添加代码),我都会遇到内存泄漏。

即使代码只简化为:

void Gspv::addCode(QPixmap &pm, QString &code)
{
    QPainter pmp(&pm);
    // here it does nothing !
}

内存泄漏是。而且无论语句是静态的还是动态的,结果都是一样的。

不加代码,内存使用量在152 Mo左右,已经够低了。添加这个简单的代码后,它会出现内存不足的问题。

我看了很多关于 QPainter 和内存泄漏的帖子,但我无法处理。

你会为此提供帮助吗?

提前致谢。

【问题讨论】:

  • 使用 QImage 代替 QPixmap。
  • 你确定画家是泄漏的源头吗?您确定创建者会构建并执行您最近的代码吗?它经常卡住......
  • 我会尝试用实际答案回复,但它已经被覆盖了,而不是一次:stackoverflow.com/questions/707492/how-do-i-paint-with-qpainter 您的代码应该超载paintEvent 并请求update。以这种方式重构它,将一个对象与一些任务分开,供paintEvent 绘制。
  • 关于泄漏:只是不清楚waypoints。其余的代码只是没有做应该做的事情。

标签: qt memory-leaks qpainter


【解决方案1】:

@AlexanderVX 根据您的评论,我更改了代码。这是新结构。

来自这个的 addFixes 方法:

void Gspv::addFixes() // waypoints layer
{

...
    addCode(icone,str); // Prob here
...
}

变成这样:

void Gspv::addFixes() // waypoints layer
{
...
    //Add code within icon
    paint = new QPainter(&icone);
    QGraphicsItem *item = new GenIcone("wayPoint", str, paint);
    delete paint;
...
}

AddCode 方法已被一个全新的类 GenIcon 取代。

.h

#ifndef GENICONE_H
#define GENICONE_H

//#include <QPixmap>
#include <QGraphicsItem>
#include <QPainter>

class GenIcone : public QGraphicsItem
{
public:
    GenIcone(const QString icone, QString code, QPainter *painter);
    QRectF boundingRect() const Q_DECL_OVERRIDE;
    QPainterPath shape() const Q_DECL_OVERRIDE;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget) Q_DECL_OVERRIDE;

    QPainter m_painter;

private :
    QString m_icone;
    QString m_code;
};

#endif // GENICONE_H

.cpp

#include "genicone.h"
#include <QtWidgets>
#include <QWidget>
#include <QStyleOptionGraphicsItem>

GenIcone::GenIcone(const QString icone, QString code, QPainter *painter)
{
    this->m_icone = icone;
    this->m_code = code;

    setAcceptHoverEvents(true);
    QStyleOptionGraphicsItem opt;
    QWidget w;

    paint(painter,&opt,&w);
}


void GenIcone::paint(QPainter *painter, const QStyleOptionGraphicsItem *item, QWidget *widget)
{
    Q_UNUSED(widget);
    Q_UNUSED(item);

    //Draw code within icon

    if (m_icone== "wayPoint") {
        painter->setFont(QFont("ArialBold",10));
        painter->eraseRect(0,20,50,18);
        painter->drawText(1,32,m_code);
        painter->end();
    }
}

QRectF GenIcone::boundingRect() const 
{
    ...
}

QPainterPath GenIcone::shape() const
{
    ...
}

所以,它可以工作,但尽管油漆过载,我仍然会出现内存泄漏。我可以做些什么来改进我的代码?

感谢您的帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    • 2014-08-26
    • 2020-05-13
    • 2017-01-23
    相关资源
    最近更新 更多