2017-05-15 79 views
1

我有一個QML ListModel的喜歡如下:在QML ListModel的獲取給定的索引值

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

然後,我有一些簡單的QML標籤喜歡如下:

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! 
} 

我的問題是,以填補支架在myListMode.get()。myValue中。 其實我需要一個條件: 如果myListModel具有一定的身份識別碼,等於我目前labelInt, 然後回到我相應的身份識別碼,否則留空空間:

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

我試過但我不確定這是否正確。

你能幫我嗎? 謝謝

+0

嘗試'ListElement {myId:「1」,myValue:「12」}''''''而不是'='。此外,請參閱此處以瞭解如何徹底搜索列表模型:http://stackoverflow.com/questions/41991438/how-do-i-find-a-particular-listelement-inside-a-listmodel-in-qml – dtech

+0

Doesn沒有工作:-( – Elena

+0

你查詢的'myId',會經常變化嗎?ListModel'的內容會經常變化嗎? – derM

回答

0

如果你的速度是你的願望,你應該映射你的條目到myId

在QML中,您可以使用InstantitatorJSObject的組合執行此操作。

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)) 
     } 
    } 
} 

釋:

Instantiator創建模型中的每個條目的QtObject。此QtObject存儲對條目模型數據的引用。這兩個屬性myID__oldID用於保持Map (JSObject) tracker最新。

myID是綁定到model.myID所以,只要這會改變它會觸發myID上的信號改變。現在我需要將地圖中的鍵從舊值更改爲新值。因此,我使用密鑰__oldID刪除條目,然後我將__oldID更新爲新的myID,並使用新密鑰將對象添加回地圖中。

我不想__oldID被綁定,因此我將它分配在Component.onCompleted

當條目被刪除時,我也從Map中刪除對象和引用,所以我保持我的地圖儘可能乾淨。

添加新條目時,Instantiator會自動爲此添加新的QtObject。現在


您可以在O(1)tracker[myID]查詢您的myIDInstantiator注意所有更改將被跟蹤。只有當特定行中的模型發生變化時纔會發生變化。

請注意,此方法會對您的內存產生負面影響,因爲它基本上會在hashmap中複製您的模型。

爲了避免這種情況,您可以在C++中實現ProxyModel,例如,根據您添加myID和實際模型索引的映射的QIdentityProxyModel。處理dataChanged-信號以使地圖保持最新狀態。 PS:我預計至少myID是獨一無二的。否則就像這樣,你可能會失去一些參考。然後使用桶來保留共享地圖中的多個條目myID

+0

謝謝@derM,真的很有意思的答案!你能解釋一下更多的代碼嗎?我是QML中的新手.. – Elena

+0

我嘗試過,如果你希望這個問題的答案更詳細,你也可以考慮創建一個新的問題,引用這個問題。 – derM

0

您需要遍歷模型以查找元素。

例子:

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

It works!Tha你好!但是,這種方法太慢了,我真的需要找到另一種解決方案:-( – Elena