Il mio enigma, formulato in generale, è: attraverso alcune azioni all'esterno di GridView, voglio calcolare le coordinate di un particolare elemento delegato in GridView basato solo su un particolare articolo di modello o indice selezionato prima.Come ottenere un componente delegato istanziato da un GridView o ListView in QML
Ho un GridView con un numero di elementi nel modello. Il delegato di GridView crea una vista in miniatura di ciascun elemento. Quando si fa clic, viene visualizzata una vista dettagliata a schermo intero dell'oggetto. Mi piacerebbe una transizione gradevole che mostri la miniatura che si espande dalla sua posizione in GridView e quando la vista dettagliata viene eliminata, ridiscendendo verso il basso in GridView.
Il trucco è che la vista dettagliata è a sua volta un delegato di una ListView in modo da poter scorrere tra le viste dettagliate una schermata alla volta. Ciò significa una soluzione che semplicemente ridimensiona l'elemento delegato di GridView o qualcosa non funzionerà. Inoltre, poiché è possibile eseguire una pagina su qualsiasi elemento in ListView, è necessario tornare a GridView basandosi solo sulle informazioni disponibili nel modello o sull'indice dell'oggetto del modello (ad esempio, non è possibile memorizzare le coordinate di MouseArea utilizzate per avviare il vista dettagliata o qualcosa del genere).
L'animazione di espansione è abbastanza semplice, poiché l'elemento delegato ha una MouseArea per il gestore di clic che conosce il proprio posizionamento, in modo che possa essere trasmesso alla funzione che avvia l'animazione. È il contrario che non riesco a capire: dall'elemento modello/indice in ListView, come faccio a capire le coordinate dell'elemento correlato in GridView?
Non riesco a trovare nulla nei documenti che sembra consentire di avere accesso a un'istanza di articolo delegato da un'istanza di elemento modello o anche un indice. GridView ha indexAt()
che restituisce l'indice in base alle coordinate. Penso che potrei arrangiarmi con il contrario, ma non sembra esistere.
Ecco un esempio più concreto. Ci scusiamo per la lunghezza; questo è il codice di esempio più breve che potrei inventare che descriva accuratamente il mio problema:
import QtQuick 1.1
Item {
id: window
width: 400
height: 200
state: "summary"
states: [
State { name: "summary"; },
State { name: "details"; }
]
transitions: [
Transition { from: "summary"; to: "details";
SequentialAnimation {
PropertyAction { target: animationRect; property: "visible"; value: true; }
ParallelAnimation {
NumberAnimation { target: animationRect; properties: "x,y"; to: 0; duration: 200; }
NumberAnimation { target: animationRect; property: "width"; to: 400; duration: 200; }
NumberAnimation { target: animationRect; property: "height"; to: 200; duration: 200; }
}
PropertyAction { target: detailsView; property: "visible"; value: true; }
PropertyAction { target: summaryView; property: "visible"; value: false; }
PropertyAction { target: animationRect; property: "visible"; value: false; }
}
},
Transition { from: "details"; to: "summary";
SequentialAnimation {
PropertyAction { target: summaryView; property: "visible"; value: true; }
// How to animate animationRect back down to the correct item?
PropertyAction { target: detailsView; property: "visible"; value: false; }
}
}
]
Rectangle {
id: animationRect
z: 1
color: "gray"
visible: false
function positionOverSummary(summaryRect) {
x = summaryRect.x; y = summaryRect.y;
width = summaryRect.width; height = summaryRect.height;
}
}
ListModel {
id: data
ListElement { summary: "Item 1"; description: "Lorem ipsum..."; }
ListElement { summary: "Item 2"; description: "Blah blah..."; }
ListElement { summary: "Item 3"; description: "Hurf burf..."; }
}
GridView {
id: summaryView
anchors.fill: parent
cellWidth: 100
cellHeight: 100
model: data
delegate: Rectangle {
color: "lightgray"
width: 95; height: 95;
Text { text: summary; }
MouseArea {
anchors.fill: parent
onClicked: {
var delegateRect = mapToItem(window, x, y);
delegateRect.width = width; delegateRect.height = height;
animationRect.positionOverSummary(delegateRect);
detailsView.positionViewAtIndex(index, ListView.Beginning);
window.state = "details";
}
}
}
}
ListView {
id: detailsView
anchors.fill: parent
visible: false
orientation: ListView.Horizontal
snapMode: ListView.SnapOneItem
model: data
delegate: Rectangle {
color: "gray"
width: 400; height: 200;
Column {
Text { text: summary; }
Text { text: description; }
}
MouseArea {
anchors.fill: parent
onClicked: {
// How do I get the coordinates to where animationRect should return?
summaryView.positionViewAtIndex(index, GridView.Visible);
window.state = "summary";
}
}
}
}
}
Qualche idea? È possibile che io stia solo andando nel modo sbagliato. Se ciò che sto cercando di fare nello specifico è impossibile, c'è un altro modo in cui dovrei essere architettato? Grazie!
Edit: Alcune idee che ho avuto (nessuno dei quali credo siano fattibili):
tenere un elenco di tutti gli elementi delegato creati, utilizzando
Component.onCompleted
eComponent.onDestruction
. Per essere utile, dovrebbe essere una mappa di elemento del modello o indice => elemento delegato. Il problema è che il basic types docs (in particolare variant) sembra indicare che questo tipo di mappa è impossibile da creare in puro QML. Sembra quindi che ciò significherebbe creare questa mappa come classe C++ e utilizzarla in QML cononCompleted
/onDestruction
all'interno del componente delegato per mantenerlo aggiornato. Sembra un po 'pericoloso e pesante per qualcosa che dovrebbe essere semplice.This mailing list post sembra indicare che la proprietà
contentItem
di Flickable può essere utilizzata per enumerare gli elementi delegati. Poi ho trovato this post definendolo una cattiva pratica. Ci sto ancora guardando, ma sono scettico sul fatto che questa sarà una soluzione legittima. Sembra troppo hacky per funzionare in modo affidabile.
Questo è tutto quello che ho ottenuto finora.
Ti chiedi solo se hai trovato soluzioni migliori o implementazioni migliori per accedere ai delegati di un modello da un altro file QML o se stai ancora utilizzando l'approccio sopra? – stackunderflow
No, per quanto posso dire questo è il modo "ufficiale" per farlo. – chazomaticus
Sembra uno dei problemi che la "magia nera" cerca di superare è la lista dei bambini che viene inquinata dai fratelli di GridView. Penso che puoi avvolgere il tuo GridView in un rettangolo, semplificando la tua lista dei bambini. Quindi semplicemente summaryView.contentItem.children [i] sembra funzionare bene. – SketchBookGames