2017-05-15 5 views
1

Ich habe ein QML Listmodel wie folgt:Get Wert für bestimmten Index in QML Listmodel

ListModel { 
id: myListModel 
ListElement {myId: "1", myValue = "12"} 
ListElement {myId: "2", myValue = "0"} 
... 
ListElement {myId: "21", myValue = "123"} 
} 

Dann habe ich einige einfache QML Labels wie folgt:

Label { 
id: myLabel1 
property int labelInt: 1 
text: myListModel.get().myValue; //Here is my problem! 
} 

Label { 
id: myLabel2 
property int labelInt: 22 
text: myListModel.get().myValue; //Here is my problem! 
} 

Mein Problem, dass Klammern zu füllen ist in myListMode.get(). myValue. In der Tat muss ich eine Bedingung: wenn myListModel einige myid hat, dass meine aktuellen labelInt gleich, Rückkehr mir dann die entsprechenden myid, sonst leeren Raum verlassen:

ich versucht:

myListModel.get(myListModel.get(myId = labelInt).myId).myValue; 

aber ich bin mir nicht sicher Es ist der richtige Weg.

Können Sie mir helfen? Vielen Dank

+0

zu behalten. Versuchen Sie 'ListElement {myId:" 1 ", myValue:" 12 "}' - ':' anstelle von '='. Siehe auch hier, um zu erfahren, wie man ein Listenmodell gründlich durchsucht: http://stackoverflow.com/questions/41991438/how-do-i-find-a-particular-listelement-inside-a-listmodel-in-qml – dtech

+0

Doesn 't work :-( – Elena

+0

Wird die 'myId', die Sie abfragen, oft variieren? Wird sich der Inhalt des' ListModel' oft ändern? – derM

Antwort

0

Wenn Sie beschleunigen Ihr Wunsch ist, sollten Sie Sie Einträge in die myId kartieren. In QML können Sie dies mit einer Kombination aus Instantitator und JSObject tun.

property var tracker: ({}) 

Instantiator { 
    model: tm 
    delegate: QtObject { 
     id: instDummy 
     property QtObject modelData: model 
     property string __oldID 
     property string myID: model.myID 

     onMyIDChanged: { 
      if (myID && __oldID !== myID) { 
       delete tracker[__oldID] 
       __oldID = myID 
       tracker[__oldID] = instDummy 
       console.log('changed', Object.keys(tracker)) 
      } 
     } 

     Component.onCompleted: { 
      __oldID = myID 
     } 
     Component.onDestruction: { 
      console.log(__oldID, modelData.myID, delete tracker[__oldID]) 
      console.log('removed', Object.keys(tracker)) 
     } 
    } 
} 

Explaination:

Die Instantiator schafft eine QtObject für jeden Eintrag in dem Modell. Diese QtObject speichert einen Verweis auf die Modelldaten des Eintrags. Die beiden Eigenschaften myID und __oldID dienen dazu, die Map (JSObject) tracker aktuell zu halten.

myID ist an die model.myID so gebunden, wenn dies ändern würde, würde das Signal auf myID ausgelöst auslösen. Jetzt muss ich den Schlüssel in der Karte vom alten Wert zum neuen Wert ändern. Daher lösche ich den Eintrag mit dem Schlüssel __oldID, dann aktualisiere ich __oldID auf den neuen myID und füge das Objekt mit dem neuen Schlüssel wieder in die Karte ein.

Ich möchte nicht __oldID gebunden werden, daher weise ich es in Component.onCompleted zu.

Wenn der Eintrag entfernt wird, entferne ich das Objekt und die Referenz aus dem Map, also halte ich meine Karte so sauber wie möglich. Wenn ein neuer Eintrag hinzugefügt wird, fügt der Instantiator automatisch einen neuen QtObject hinzu.


Jetzt können Sie Ihre myID in O(1) mit tracker[myID] abfragen.Die Instantiator sorgt dafür, dass alle Änderungen nachverfolgt werden. Es ändert sich nur, wenn das Modell in der bestimmten Zeile geändert wird.

Beachten Sie, dass diese Methode Ihr Gedächtnis belasten wird, da es Ihr Modell im Wesentlichen in der Hashmap verdoppeln wird.

Um dies zu vermeiden, könnten Sie eine ProxyModel in C++ implementieren, z. basierend auf dem QIdentityProxyModel, dem Sie eine Zuordnung des myID und des aktuellen Modellindex hinzufügen. Behandle das dataChanged-Signal, um diese Karte auf dem neuesten Stand zu halten.

PS: Ich erwarte, dass mindestens die myID ist einzigartig. Andernfalls könnten Sie einige Referenzen verlieren. Verwenden Sie Buckets, um mehrere Einträge in der Karte für die gemeinsamen myID

+0

Danke @derM, wirklich interessante Antwort! Könnten Sie den Code ein bisschen mehr erklären, bitte? Ich bin neu in QML .. – Elena

+0

Ich habe versucht,. Für mehr Informationen lesen Sie die Dokumentation, oder fragen Sie speziell, wo Ihre Probleme noch sind.Wenn Sie erwarten, dass die Antwort auf diese Frage sehr detailliert ist, können Sie auch in Erwägung ziehen, eine neue Frage zu erstellen, die auf diese verweist. – derM

0

Sie müssen Ihr Modell durchlaufen, um das Element zu finden.

Beispiel:

import QtQuick 2.2 
import QtQuick.Window 2.2 
import QtQuick.Controls 1.4 

ApplicationWindow { 

    function findElement(myModel, myId) { 
     for(var i = 0; i < myModel.count; i++) { 
      var element = myModel.get(i); 

      if(myId == element.myId) { 
       console.log("Found element: ", i); 
       return element.myId; 
      } 
     } 
     return ""; 
    } 


    id: window 
    visible: true 

    TableView { 
     y: 70 
     width: 500 

     TableViewColumn { 
      role: "myId" 
      title: "myId" 
      width: 100 
     } 

     TableViewColumn { 
      role: "myValue" 
      title: "myValue" 
      width: 100 
     } 

     model: myListModel 

     ListModel { 
      id: myListModel 
      ListElement 
      { 
       myId: "1" 
       myValue: "12" 
      } 
      ListElement 
      { 
       myId: "2" 
       myValue: "0" 
      } 
      ListElement 
      { 
       myId: "21" 
       myValue: "123" 
      } 
     } 
    } 

    Label 
    { 
     id: myLabel1 
     property int labelInt: 1 
     x: 0 
     text: findElement(myListModel, labelInt); 
    } 

    Label 
    { 
     id: myLabel2 
     property int labelInt: 22 
     x: 100 
     text: findElement(myListModel, labelInt); 
    } 
} 
+0

Es funktioniert! Tha Danke dir! Allerdings verlangsamt diese Methode das Programm so sehr, dass ich wirklich eine andere Lösung finden muss :-( – Elena

Verwandte Themen