关闭 QDialog 窗口是不是会删除其动态添加的 UI 元素?
Posted
技术标签:
【中文标题】关闭 QDialog 窗口是不是会删除其动态添加的 UI 元素?【英文标题】:Does closing a QDialog window delete its dynamically added UI elements?关闭 QDialog 窗口是否会删除其动态添加的 UI 元素? 【发布时间】:2018-09-12 05:48:44 【问题描述】:我的应用程序中有一个 QDialog 窗口,我正在通过此代码为其布局动态添加一个 QComboBox
Orderdialog.cpp
void Orderdialog::addElements()
ui->setupUi(this);
msgComboBox = new QComboBox();
lbl = new QLabel();
lbl->setText("Message");
ui->formLayout->addRow(lbl,msgComboBox);
(msgComboBox & lbl在头文件中定义)
根据this question设置属性会在对话框对象的close()事件被执行时删除。
我想知道是删除这些动态添加的msgComboBox & lbl 还是需要在Orderdialog类的析构函数中手动删除?
【问题讨论】:
什么是msgAliasComboBox
?
抱歉打错了,我更正了
将qDebug()
放入孩子的析构函数中,您将很容易检查。
【参考方案1】:
在 Qt 中:
当QObject
s 被摧毁时,它们会摧毁他们的孩子。
当一个QWidget被关闭时,它不会被删除,除非Qt::WA_DeleteOnClose
属性被建立。
一个QWidget是一个QObject所以它也符合第一点,所以一个QWidget是另一个QWidget的孩子至少有3种可能:
您在构造函数中传递父 QWidget。 您使用setParent()
方法。
当您通过布局建立它时,因为您的父级将是建立布局的小部件。
在lbl
和msgComboBox
被传递给布局的情况下,这将是已建立的QWidget
的子代,因为我不知道.ui 不能说谁是他的父母,但我可以说和窗口有血缘关系。
所以当窗口被销毁时,你的孩子也会被销毁,而这些孩子也会销毁他们的孩子,所以 lbl 和 msgComboBox 会被销毁,所以你只需要setAttribute(Qt::WA_DeleteOnClose)
这样 lbl、msgComboBox 和相同的 Orderdialog 就可以了窗口关闭时删除。
【讨论】:
所以如果我在delete ui
之后添加delete msgComboBox
和delete lbl
会导致异常吗?
虽然布局重新设置了小部件的父级,但作为一个好习惯,我只需在小部件创建时设置正确的父级;这样可以确保在出现异常时正确删除它们,并且养成这种习惯可以确保您不会冒险泄漏可能未添加到布局中的小部件。此外,这是您对代码的未来维护者的一个帮助 - 阅读代码并看到在没有父级的情况下创建的小部件在我脑海中敲响了几个钟声,我必须仔细检查它们是否被明确地重新设置/删除如果确实添加到布局确实会重新父级。
@eyllanesc:Qt 无法验证对象是否还活着,除非您使用 QPointer
(在 QObject
销毁时自动失效)。如果 OP 使用裸指针 Qt 无法验证某件事 - 如果该对象已被其父级删除,那么您现在拥有的只是一个悬空指针,再次删除时将导致不可预测的结果。
@eyllanesc:没有什么可悲的 AFAIK - 有点代码膨胀,降低了对象破坏的性能,略微降低了对象访问的性能。但同样,最大的问题是与您项目的其他维护者的沟通:如果我看到 QPointer
我立即怀疑有一些“奇怪”的生命周期正在发生(因此你需要一些方法来检查对象是否仍然存在活着),并且必须对其进行调查;就好像您对所有事情都使用了std::shared_ptr
:它确实有效,但它让读者怀疑正在进行所有权共享。
让我们补充一点,在文档的示例中,对话框通常是模态的,并在堆栈中的一个非常简单的插槽中创建,在这种情况下,您不需要 Qt::WA_DeleteOnClose
标志。以上是关于关闭 QDialog 窗口是不是会删除其动态添加的 UI 元素?的主要内容,如果未能解决你的问题,请参考以下文章
Qt自定义窗口,继承自QDialog,执行后返回rejected的问题分析
如何使用 PyQt 在窗口中切换布局? (不关闭/打开窗口)