我创建了一个标签来显示一些信息..它的工作方式,如果我需要显示图像,我将其设置在标签上。
class PreviewLabel : public QLabel
{
public:
explicit PreviewLabel(QWidget *parent = 0) :
QLabel(parent)
{
this->setWindowFlags(Qt::Popup);
}
protected:
virtual void leaveEvent(QEvent *)
{
this->close();
}
};
void showImageSlot()
{
QImage preview = getSomeImage();
if(preview.isNull())
return;
PreviewLabel* previewShow = new PreviewLabel();
previewShow->setPixmap(QPixmap::fromImage(preview));
previewShow->show();
}
这有内存泄漏 - PreviewLabel
对象永远不会被删除
(这可能就是它起作用的原因。)
我尝试在previewShow->deleteLater();
之后添加show()
,图片没有显示。
我也试着不把它作为指针,但图像没有显示(见下面的代码)
从技术上讲,它会显示但会立即被杀死...因为程序到达showImageSlot
函数的末尾。
void showImageSlot()
{
QImage preview = getSomeImage();
if(preview.isNull())
return;
PreviewLabel previewShow;
previewShow.setPixmap(QPixmap::fromImage(preview));
previewShow.show();
}
因此previewShow
对象需要比该函数更长的生命周期...但是如何?
我更喜欢不把它变成成员变量 - 但我也尝试将它变成一个(在类析构函数中删除)。
if(m_previewShow == NULL)
m_previewShow = new PreviewLabel();
m_previewShow->setPixmap(QPixmap::fromImage(preview));
m_previewShow->show();
这......在第一次通话时崩溃。
如何展示它,最好不必将其作为类成员变量?
我在考虑让对象在leaveEvent
中自杀 - 这可能吗?
编辑 - 有两个人提出了相同的建议 - 我在this->deleteLater();
中添加了leaveEvent
我试过,程序似乎运行良好 -
但我也在Valgrind中运行它并且程序崩溃了,日志文件说
--15595-- memcheck GC: 32768 nodes, 30902 survivors ( 94.3%)
--15595-- memcheck GC: increase table size to 65536
==15595== Invalid free() / delete / delete[] / realloc()
==15595== at 0x402ACFC: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==15595== by 0x805D495: MainWindow::~MainWindow() (mainwindow.cpp:234)
==15595== by 0x4E7ED02: qDeleteInEventHandler(QObject*) (in /usr/lib/i386-linux-gnu/libQtCore.so.4.8.1)
(引用的行号位于包含showImageSlot()
函数的主类的析构函数的末尾)
答案 0 :(得分:0)
好的,列出所有变种。
首先是初始代码。只需将deleteLater()
添加到leaveEvent()
,当鼠标离开窗口小部件时,标签就会被销毁。
class PreviewLabel : public QLabel
{
public:
explicit PreviewLabel(QWidget *parent = 0) :
QLabel(parent)
{
this->setWindowFlags(Qt::Popup);
}
protected:
virtual void leaveEvent(QEvent *)
{
this->close();
this->deleteLater();
}
};
void showImageSlot()
{
QImage preview = getSomeImage();
if(preview.isNull())
return;
PreviewLabel* previewShow = new PreviewLabel();
previewShow->setPixmap(QPixmap::fromImage(preview));
previewShow->show();
}
第二,使用成员变量在mose离开小部件后销毁自己。请注意,必须使用QPointer
保护成员变量,以便始终知道它是否存在。
class PreviewLabel : public QLabel
{
public:
explicit PreviewLabel(QWidget *parent = 0) :
QLabel(parent)
{
this->setWindowFlags(Qt::Popup);
}
protected:
virtual void leaveEvent(QEvent *)
{
this->close();
this->deleteLater();
}
};
// somewhere in member declaration
// this should be QPointer in order to detect label destroy
QPointer<QLabel> m_previewShow;
...
void showImageSlot()
{
if(!m_previewShow)
m_previewShow = new PreviewLabel();
m_previewShow->setPixmap(QPixmap::fromImage(preview));
m_previewShow->show();
}