我们有一个相当大的QtQuick应用程序,其中有很多模态对话框。所有这些模式共享一致的外观和行为,并留下了按钮,右键,内容和其他警告小部件。我们用下面的基类(PFDialog.qml):关闭应用程序时出现QQuickItem析构函数/ changeListeners崩溃(Qt 5.6)
Window {
property alias content: contentLayout.children
ColumnLayout {
id: contentLayout
}
}
,并宣布以下列方式对话框(main.qml):
Window {
visible: true
property var window: PFDialog {
content: Text { text: "Foobar" }
}
}
的问题是,当应用程序被关闭,一个段错误发生在QQuickItem析构函数中。这段错误很难重现,但这是一个绝妙的实现方式:在调试模式下,Visual Studio将释放的内存填充0xDDDDDDD,每次触发段错误。
完整的示例应用程序可以在这里找到:https://github.com/wesen/testWindowCrash
坠机发生在QQuickItem::~QQuickItem
:
for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
QQuickAnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate();
if (anchor)
anchor->clearItem(this);
}
这样做的原因是,我们的对话的内容(在上面的例子中,文本项)是主窗口的QObject子元素,但是是对话窗口的可视子元素。关闭应用程序时,首先销毁对话窗口,并且在删除文本项目时,对话窗口(仍然注册为changeListener)已过时。
现在我的问题是:
- 这是一个QtQuick错误?如果对话框注销自己作为它的孩子的变化侦听器,当它被销毁时(我认为应该)
- 是我们的
property alias content: layout.children
模式正确,还是有更好的方法来做到这一点?在声明默认属性别名时也会发生这种情况。
为了完整起见,以下是我们如何在我们的应用程序中对其进行修补。当内容发生变化时,我们将所有项目重新分配给布局项目。优雅之一,你会大家都同意。
function reparentTo(objects, newParent) {
for (var i = 0; i < objects.length; i++) {
qmlHelpers.qml_SetQObjectParent(objects[i], newParent)
}
}
onContentChanged: reparentTo(content, contentLayout)
请问您可以使用自包含的测试用例编辑问题吗? –
对不起,我不确定我关注你。这与我所能做到的完全一样(顶部的8行是整个应用程序)。你可以克隆存储库,如果你想有一些内置的东西。 –
哦,好吧,对不起,我没有注意到这一切。谢谢! –