QT QPixmap QImage内存泄漏
无论是在代码中还是在UI中设置icon都会产生内存泄漏
大概看了下,好像是QPixmap的data_ptr的引用计数,到不了1/0(查看引用计数,释放后,理论上应回到1)
试了下,仅以下两种方式不会产生内存泄漏:
1、从 XPM加载:
img = QPixmap(result); //result为 static const char *result[] = {。。。。}
或
ui.label->setPixmap(QPixmap(result));
2、现场绘制:
img = QPixmap(16, 16);
img.fill(Qt::transparent);
QPainter painter(&img);
painter.drawLine(1, 1, 15, 15);
。。。
painter.end();
ui.label->setPixmap(img);
但是,使用XPM,图片的质量太差
png
xpm
所以决定自己绘制。
步骤一、使用代码生成自定义图片的数据文件:
w(ushort)h(ushort)bytesperpixel(uchar)+若干RGBA数据
例:
16(ushort)16(ushort)4(uchar)+{uint32(RGBA)*16*16}
步骤二、加载、显示
CLeeBuffer.h 自定义图片数据的存取类
#include <QByteArray> class CLeeBuffer { public: CLeeBuffer() {} ~CLeeBuffer() {} CLeeBuffer& Store(char val) { m_data.append(1, val); return *this; } CLeeBuffer& Store(uchar val) { m_data.append(1, (char)val); return *this; } CLeeBuffer& Store(ushort val) { m_data.append((const char*)&val, 2); return *this; } CLeeBuffer& Store(short val) { m_data.append((const char*)&val, 2); return *this; } CLeeBuffer& Store(uint val) { m_data.append((const char*)&val, 4); return *this; } CLeeBuffer& Store(int val) { m_data.append((const char*)&val, 4); return *this; } CLeeBuffer& Store(void* pBuf, int len) { m_data.append((const char*)pBuf, len); return *this; } CLeeBuffer& Store(QByteArray val) { m_data.append(val); return *this; } bool Read(int& nPos, char& val) { if (nPos + sizeof(val) > m_data.size()) return false; auto pBuf = m_data.constData(); memcpy(&val, pBuf + nPos, sizeof(val)); nPos += sizeof(val); return true; } bool Read(int& nPos, uchar& val) { if (nPos + sizeof(val) > m_data.size()) return false; auto pBuf = m_data.constData(); memcpy(&val, pBuf + nPos, sizeof(val)); nPos += sizeof(val); return true; } bool Read(int& nPos, ushort& val) { if (nPos + sizeof(val) > m_data.size()) return false; auto pBuf = m_data.constData(); memcpy(&val, pBuf + nPos, sizeof(val)); nPos += sizeof(val); return true; } bool Read(int& nPos, short& val) { if (nPos + sizeof(val) > m_data.size()) return false; auto pBuf = m_data.constData(); memcpy(&val, pBuf + nPos, sizeof(val)); nPos += sizeof(val); return true; } bool Read(int& nPos, uint& val) { if (nPos + sizeof(val) > m_data.size()) return false; auto pBuf = m_data.constData(); memcpy(&val, pBuf + nPos, sizeof(val)); nPos += sizeof(val); return true; } bool Read(int& nPos, int& val) { if (nPos + sizeof(val) > m_data.size()) return false; auto pBuf = m_data.constData(); memcpy(&val, pBuf + nPos, sizeof(val)); nPos += sizeof(val); return true; } bool Read(int& nPos, void* pBuf, int len) { if (nPos + len > m_data.size()) return false; auto pBuf_ = m_data.constData(); memcpy(pBuf, pBuf_ + nPos, len); nPos += len; return true; } QByteArray getData() { return m_data; } private: QByteArray m_data; };
QLeePixmap.h
#include "CLeeBuffer.h" #include <QPixmap> #include <QFile> #include <QString> #include <QPainter> #include <QPen> class QLeePixmap { public: QLeePixmap() {} QLeePixmap(QString sFile) { load(sFile); } void load(QString sFile) { union { int IntVal; struct { uchar b, g, r, a; }Color; }Color32; QFile mFile(sFile); if (mFile.open(QIODevice::ReadOnly)) { CLeeBuffer leeBuf; leeBuf.Store(mFile.readAll()); mFile.close(); ushort w = 0, h = 0; uchar bytesPerPixel = 0; int nPos = 0; leeBuf.Read(nPos, w); leeBuf.Read(nPos, h); leeBuf.Read(nPos, bytesPerPixel); m_pixmap = QPixmap(w, h); m_pixmap.fill(Qt::transparent); QPainter painter(&m_pixmap); QPen pen; for (ushort row = 0; row < h; row++) { for (ushort col = 0; col < w; col++) { if (!leeBuf.Read(nPos, Color32.IntVal)) { } pen.setColor(QColor(Color32.Color.r, Color32.Color.g, Color32.Color.b, Color32.Color.a)); painter.setPen(pen); painter.drawPoint(col, row); } } painter.end(); } } QPixmap& getPixmap() { return m_pixmap; } private: QPixmap m_pixmap; };
使用:
QLeePixmap m_img;//.h
//.cpp
m_img.load(QString::fromLocal8Bit("。。。。\\img_connected.sim")); ui.label->setPixmap(m_img.getPixmap());
注 对微小尺寸的图片适用,对大尺寸不太适用——因为生成的文件大小近似 BMP格式的文件大小