In QtQuick 2 utilizzando il QtQuick Controls è possibile creare applicazioni desktop complesse. Tuttavia, mi sembra che l'intera interfaccia utente debba essere dichiarata e creare tutto in una volta all'inizio dell'app. Tutte le parti che non si desidera utilizzare ancora (ad esempio, il File-> Apri finestra di dialogo) devono ancora essere creati, ma sono nascosti, in questo modo:Qt 5 QML app con un sacco di finestre o di interfacce utente complesse
ApplicationWindow {
FileDialog {
id: fileOpenDialog
visible: false
// ...
}
FileDialog {
id: fileSaveDialog
visible: false
// ...
}
// And so on for every window in your app and every piece of UI.
Ora, questo può andare bene per le applicazioni semplici, ma per quelli complessi o le app con molti dialoghi sicuramente questa è una cosa da pazzi? Nel modello tradizionale di QtWidgets creerai dinamicamente il tuo dialogo quando necessario.
So che ci sono alcune soluzioni per questo, ad esempio, puoi usare uno Loader
o persino creare oggetti QML dinamicamente direttamente in javascript, ma sono molto brutti e perdi tutti i vantaggi della bella sintassi QML. Inoltre, non è possibile "scaricare" realmente i componenti. Bene Loader
afferma che puoi ma l'ho provato e la mia app si è bloccata.
Esiste una soluzione elegante a questo problema? O devo semplicemente mordere il proiettile e creare tutta l'interfaccia utente potenziale per la mia app in una sola volta e poi nasconderne la maggior parte?
Nota: this page ha informazioni sull'utilizzo di Loader
s per aggirare questo problema, ma come potete vedere non è una soluzione molto bella.
Edit 1 - Perché Loader non ottimale?
Ok, per mostrare il perché Loader
non è poi così piacevole, considerare questo esempio che inizia un compito complesso e attende un risultato. Supponiamo che - a differenza di tutti gli esempi banali che di solito si danno - il compito abbia molti input e diversi output.
Questa è la soluzione Loader
:
Window {
Loader {
id: task
source: "ComplexTask.qml"
active: false
}
TextField {
id: input1
}
TextField {
id: output1
}
Button {
text: "Begin complex task"
onClicked: {
// Show the task.
if (task.active === false)
{
task.active = true;
// Connect completed signal if it hasn't been already.
task.item.taskCompleted.connect(onTaskCompleted)
}
view.item.input1 = input1.text;
// And several more lines of that...
}
}
}
function onTaskCompleted()
{
output1.text = view.item.output1
// And several more lines...
// This actually causes a crash in my code:
// view.active = false;
}
}
Se lo facevo senza Loader
, potrei avere qualcosa di simile:
Window {
ComplexTask {
id: task
taskInput1: input1.text
componentLoaded: false
onCompleted: componentLoaded = false
}
TextField {
id: input1
}
TextField {
id: output1
text: task.taskOutput1
}
Button {
text: "Begin complex task"
onClicked: task.componentLoaded = true
}
}
che ovviamente è modo più semplice. Quello che voglio chiaramente è un modo per caricare lo ComplexTask
e avere tutte le sue relazioni dichiarative attivate quando componentLoaded
è impostato su true, quindi avere le relazioni disconnesse e scaricare il componente quando componentLoaded
è impostato su false. Sono abbastanza sicuro che non ci sia modo di fare qualcosa di simile a Qt al momento.
Perché è la soluzione Loader non è bello? Perché è brutto? Se la tua app si arresta in modo anomalo quando l'impostazione è attiva su false, è un bug nell'app o nel codice Qt e non è un argomento contro l'utilizzo di Loader. Perché impostare la visibilità delle cose su false in una grande applicazione è pazzesca? – Mitch
Sembra un po 'come ti sto interrogando, ma è solo una serie di domande davvero curiose. :) – Mitch
Vedi gli aggiornamenti. E impostare la visibilità su false nelle app di grandi dimensioni è folle perché il componente è ancora caricato e utilizza le risorse. È come quei "siti web di una pagina" che precaricano tutto. Sono ok se hai solo poche pagine, ma non puoi usare quella tecnica se stai facendo un eBay o Amazon. – Timmmm