最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Get value for given index in QML LISTMODEL - Stack Overflow

programmeradmin0浏览0评论

I have a QML ListModel like follows:

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

Then I have some simple QML labels like follows:

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

My problem is to fill that brackets in myListMode.get().myValue. In fact I need a condition: if myListModel has some myId that equals my current labelInt, then return me the corresponding myId, otherwise leave empty space:

I tried with:

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

but I am not sure It's the proper way.

Can you help me? Thank you

I have a QML ListModel like follows:

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

Then I have some simple QML labels like follows:

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

My problem is to fill that brackets in myListMode.get().myValue. In fact I need a condition: if myListModel has some myId that equals my current labelInt, then return me the corresponding myId, otherwise leave empty space:

I tried with:

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

but I am not sure It's the proper way.

Can you help me? Thank you

Share Improve this question asked May 15, 2017 at 8:49 AleAle 3052 gold badges8 silver badges18 bronze badges 7
  • Try ListElement {myId: "1", myValue: "12"} - : instead of =. Also, see here for how to search thorough a list model: stackoverflow./questions/41991438/… – dtech Commented May 15, 2017 at 9:34
  • Doesn't work :-( – Ale Commented May 15, 2017 at 9:38
  • Will the myId that you query, vary often? Will the content of the ListModel change often? – derM Commented May 15, 2017 at 10:09
  • Yes, it's always different! – Ale Commented May 15, 2017 at 10:28
  • 1 During the runtime of the programm: Will data be appended and/or removed from the ListModel? Will, for one entry in the ListModel the values be constant over time, may all change, or is at least myId constant? – derM Commented May 15, 2017 at 10:51
 |  Show 2 more ments

2 Answers 2

Reset to default 1

If you speed is your desire, you should map you entries to the myId.

In QML you can do this with a bination of a Instantitator and a JSObject.

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

Explanation:

The Instantiator creates a QtObject for each entry in the model. This QtObject stores a reference to the model data of the entry. The two properties myID and __oldID are used to keep the Map (JSObject) tracker up to date.

myID is bound to the model.myID so, whenever this would change it would trigger the signal on myIDchanged. Now I need to change the key in the map from the old value to the new value. Therefore I delete the entry with the key __oldID, then I update __oldID to the new myID and add the object back into the map, with the new key.

I don't want __oldID to be bound, therefore I assign it in Component.onCompleted.

When the entry is removed, I remove the object and the reference from the Map as well, so I keep my map as clean as possible.

When a new entry is added, the Instantiator will automatically add a new QtObject for this.


Now you can query your myID in O(1) with tracker[myID]. The Instantiator takes care that all changes will be tracked. It only changes, when there is a change to the model in the specific row.

Note that this method will take a toll on your memory, as it will basically duplicate your model in the hashmap.

To avoid this, you might implement a ProxyModel in C++, e.g. based on the QIdentityProxyModel to which you add a mapping of the myID and the actuall model index. Handle the dataChanged-signal to keep that map up-to-date.

PS: I expect that at least the myID is unique. Otherwise like this, you might lose some references. Use buckets then, to keep multiple entries in the map for shared myID's

You need to loop through your model to find the element.

Example:

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)

  1. 暂无评论