[英]Deleting Pointer to widget Qt C++
我是Qt的新手,我对如何删除小部件非常困惑。 我正在阅读视频,我想在读取视频帧时显示QProgressbar,然后在加载视频时删除此QProgressbar。
我用两种不同的方式做到了:
使用指针
QWidget* wd = new QWidget(); QProgressBar* pB = new QProgressBar(wd); QLabel* label = new QLabel(wd); //setting geometry and updating the label and progressbar wd->deleteLater(); wd->hide();
这段代码写在一个类中,我假设当调用这个类的析构函数时,小部件将被删除所有的子节点,但是没有发生,每次我再次运行这个函数时,创建一个新的小部件而不隐藏或者删除前一个(注意:我试图从小部件中删除标签和进度条,假设它们将从小部件内部消失,但这不会发生“删除(pB);”)
使用对象
QWidget wd; QProgressBar pB(&wd); QLabel label(wd); //setting geometry and updating the label and progressbar wd.deleteLater(); wd.hide();
当我运行相同的代码但使用对象而不是指针时,它运行完全如我所希望的那样,每次运行该函数时,旧的小部件都会被销毁并创建一个新的小部件。
注意: - 当我关闭主窗口时,如果指针,小部件wd仍然存在,程序不会终止,直到我手动关闭它们 - 如果是对象,当我关闭主窗口时,一切都关闭,程序正确终止。
我需要有人解释我为什么会发生这种情况以及如果我有一个指向小部件的指针向量来删除该向量内的所有指针而没有任何内存泄漏
在典型的C ++中,规则是“为每个new
写一个delete
”。 一个更高级的规则是“可能不会写new
或delete
并以RIAA模式埋葬”。 Qt在这方面改变了规则,因为它引入了自己的内存管理范例。 它基于父/子关系。 new
ed的QWidget
可以给出parentWidget()
。 当parentWidget()
被销毁时,它的所有子parentWidget()
都将被销毁。 因此,在Qt中,通常的做法是使用new
在堆栈上分配对象,给它们一个父级,并且永远不要自己delete
内存。 QLayout
规则变得更加复杂,有时候Qt对象会占用小部件,有时则不会。
在您的情况下,您可能不需要deleteLater
调用。 这会向Qt的内部事件循环发布消息。 消息说:“当你有机会时删除我!” 如果你想在班级管理wd
只要给它的父this
。 删除类后,将删除整个父/子树。
这一切都非常简单。 QObject
派生类与任何其他C ++类一样,但有一个例外:如果QObject
有子QObject
,它将删除其析构函数中的子节点。 请记住, QWidget
是一个QObject. If you have an instance allocated using
QObject. If you have an instance allocated using
new` QObject. If you have an instance allocated using
,你必须删除它,或者确保某些东西(一个智能指针!)。
当然,尝试delete
未动态分配的内容是一个错误,因此:
如果没有动态分配一个QObject
, 不 deleteLater
或delete
它。
如果不动态分配QObject
的子QObject
,请确保在对象被破坏之前它们已经消失。
此外, 不要隐藏您即将破坏的小部件 。 没有用。
要自己管理窗口小部件生命周期,您应该使用智能指针:
class MyClass {
QScopedPointer<QWidget> m_widget;
public:
MyClass() :
widget{new QWidget};
{
auto wd = m_widget->data();
auto pb = new QProgressBar{wd};
auto label = new QLabel{wd};
}
};
当你破坏MyClass
,范围指针的析构函数将删除小部件实例,其QObject::~QObject
析构函数将删除其子级。
当然,这些都不是必需的:您应该只是将对象创建为类的直接成员:
class MyClass {
// The order of declaration has meaning! Parents must precede children.
QWidget m_widget;
QProgressBar m_bar{&m_widget};
QLabel m_label{&m_widget};
public:
MyClass() {}
};
通常,您将使用子窗口小部件的布局:
class MyClass {
QWidget m_widget;
QVBoxLayout m_layout{&m_widget};
QProgressBar m_bar;
QLabel m_label;
public:
MyClass() {
m_layout.addWidget(&m_bar);
m_layout.addWidget(&m_label);
}
};
当您向布局添加窗口小部件时,它会将它们重新设置为已设置布局的窗口小部件。
编译器生成的析构函数如下所示。 你不能编写这样的代码,因为编译器生成的代码会双重破坏已经被破坏的对象,但让我们假装你可以。
MyClass::~MyClass() {
m_label.~QLabel();
m_bar.~QProgressBar();
m_layout.~QVBoxLayout();
// At this point m_widget has no children and its `~QObject()` destructor
// won't perform any child deletions.
m_widget.~QWidget();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.