Abbiamo un'applicazione QtQuick abbastanza grande, con molte finestre di dialogo modali. Tutte queste modali condividono un aspetto e un comportamento coerente e hanno lasciato Pulsanti, rightButtons, un contenuto e ulteriori widget di avviso. Usiamo la seguente classe di base (PFDialog.qml):Blocco in QQuickItem destructor/changeListeners durante la chiusura dell'applicazione (Qt 5.6)
Window {
property alias content: contentLayout.children
ColumnLayout {
id: contentLayout
}
}
e dichiarare dialoghi nel modo seguente (main.qml):
Window {
visible: true
property var window: PFDialog {
content: Text { text: "Foobar" }
}
}
Il problema è che, quando viene chiuso l'applicazione, a segfault accade nel distruttore QQuickItem. Questo segfault è difficile da riprodurre, ma questo è un modo sicuro per farlo accadere: con Visual Studio in modalità di debug, la memoria liberata è piena di 0xDDDDDDD con trigger di segfault ogni volta.
applicazione di esempio completo può essere trovato qui: https://github.com/wesen/testWindowCrash
L'incidente avviene in QQuickItem::~QQuickItem
:
for (int ii = 0; ii < d->changeListeners.count(); ++ii) {
QQuickAnchorsPrivate *anchor = d->changeListeners.at(ii).listener->anchorPrivate();
if (anchor)
anchor->clearItem(this);
}
La ragione di questo è che il contenuto del nostro dialogo (l'elemento di testo nell'esempio di cui sopra) è un figlio QObject della finestra principale, ma un elemento visivo della finestra di dialogo. Quando si chiude l'applicazione, la finestra di dialogo viene prima distrutta e al momento dell'eliminazione della voce di testo, la finestra di dialogo (ancora registrata come changeListener) è obsoleta.
Ora la mia domanda è:
- è presente un bug QtQuick? Se la finestra di dialogo si cancella da sola come ChangeListener per i suoi figli quando viene distrutta (penso che dovrebbe)
- il nostro modello
property alias content: layout.children
è corretto oppure esiste un modo migliore per farlo? Ciò accade anche quando si dichiara un alias di proprietà predefinito.
Per motivi di completezza, ecco come l'abbiamo risolto nella nostra applicazione. Quando il contenuto cambia, ripariamo tutti gli articoli all'elemento di layout. A di eleganza, come concorderete tutti.
function reparentTo(objects, newParent) {
for (var i = 0; i < objects.length; i++) {
qmlHelpers.qml_SetQObjectParent(objects[i], newParent)
}
}
onContentChanged: reparentTo(content, contentLayout)
Puoi modificare la domanda con un caso di test autonomo, per favore? –
Mi dispiace, non sono sicuro che ti stia seguendo. Questo è autonomo quanto posso andare (le 8 righe in alto sono l'intera applicazione). Puoi clonare il repository se vuoi avere qualcosa costruito fuori dalla scatola. –
Oh, OK, scusa non ho capito che era tutto. Grazie! –