我可以根据需要显示创建的对象(QLabel的子类)吗? (我的问题是删除它)

时间:2016-03-16 18:27:09

标签: c++ qt qwidget

我创建了一个标签来显示一些信息..它的工作方式,如果我需要显示图像,我将其设置在标签上。

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()函数的主类的析构函数的末尾)

1 个答案:

答案 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();    

}