QML ListView hidden delegate item
Asked Answered
P

4

13

Is there any way to hide certain item in ListView?

import QtQuick 2.4
import QtQuick.Controls 1.3
import QtQuick.Window 2.2

ApplicationWindow {
    title: qsTr("Hello World")
    width: 640
    height: 480
    visible: true



    ListView {
        anchors.fill: parent

        model: ListModel {
            ListElement { color: "red"; visible: true}
            ListElement { color: "green"; visible: false}
            ListElement { color: "blue"; visible: true}
        }

        delegate: Rectangle {
            width: parent.width
            height: model.visible ? 30 : 0
            color: model.color
            visible: model.visible
            enabled: model.visible
        }
    }
}

Solution above would be good if only ListView could ignore invisible Items' height.

Setting height to 0 manually is bad for performance so I need a better solution. Could you help me?

Pattison answered 8/9, 2015 at 9:38 Comment(17)
What's bad about height: model.visible ? 30 : 0 ?Lithia
I think it will cause ListView to reposition all of its items. Of course it's not a problem when there are 100 of them. But with, for example 100000, it may be a little bit slower.Pattison
Did you tested it? ListView just creates delegates on demand, i.e. only the visible delegates are created and that's dependent on the current viewport. Can you show simultaneously 100K delegates?Lithia
Good point! I did not think about it. Your answer covers it all. Thank you;)Pattison
@BaCaRoZzo, wanna answer this so we can see that it's solved? :)Gesner
@Gesner isn't there a question which is similar to/duplicate of this one? If so I would go for deletion more than answering. Otherwise it would be worth an answer.Lithia
@Lithia no idea. :pGesner
@Gesner lighting fast... :D k, I'm going to search for that.Lithia
I tested it in a project of mine and my ListView lags when hiding 2k+ delegate. Since there height is 0, they can all fit on the viewport and the ListView creates them all. I set visible and enabled to false and height to 0.Aubarta
And for information the similar question was this one : #19208413 I could swear the answer I commented on was working at the time, but it doesn't on my project :(Aubarta
@Aubarta nice catch, thanks. Well, as said it comes down to test the code - as you did - before judging. As for the different behaviour, the ListView implementation changed in the last releases and I think that it can be a reason for the observed change. For C++ models tuning the data() can help. In the QML site using a top-level Item in the delegate vs. a Rectangle, limit the state information in the delegate as well as avoid painting the background can improve performances. Tips may still vary a lot, depending on the model, the Qt version, tough ground. Btw, flagged as duplicate.Lithia
In the newest Qt versions, setting either 'visible' or 'enabled' does not help. I saw your solution GrecKo and wanted to give it a try, but as BaCaRoZzo mentioned, ListView had some implementation changes and now it's not working. Having second model that is populated basing on the first model is an option, but it is not a performance-friendly solution.Pattison
@Aubarta I've played around with ListView a little bit. Using Loaders does not help either. Now, if you remove the hack in this example it runs smoothly. it's like it is accounting the presence of the missing delegate for scrolling the view. Asking the mailing list could definitely help.Lithia
@Lithia I don't understand what you are trying to show in your exampleAubarta
Sorry. I was just asking myself if It was more a wrong scrolling behaviour than an actual performance issue. Uhm, probably a stupid guessing. :)Lithia
Thanks, this issue answered my question.Sera
Does this answer your question? Hide an item (delegate) inside a ListView QMLWe
P
3

I hope this will solve the problem. For a beginner like me, solving this question has helped in understanding qml a bit more.

import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Window 2.0

ApplicationWindow {
    width: 640
    height: 480
    visible: true

ListView {
    id: displayListView
    anchors.fill: parent
    model: displayDelegateModel
}

ListModel {
    id: myModel
    ListElement { colo: "orange"; visible: true}
    ListElement { colo: "red"; visible: false}
    ListElement { colo: "white"; visible: true}
    ListElement { colo: "black"; visible: false}
    ListElement { colo: "green"; visible: true}
    ListElement { colo: "yellow"; visible: false}
}

VisualDataModel {
    id: displayDelegateModel

    delegate:  Rectangle {
        width: parent.width
        height: 30
        color: colo

        Text {
            text: colo
            anchors.centerIn: parent
            font.bold: true
            font.pixelSize: 20
        }
    }

    model: myModel

    groups: [
        VisualDataGroup {
            includeByDefault: false
            name: "visible"
        }
    ]

    filterOnGroup: "visible"

    Component.onCompleted: {
        var rowCount = myModel.count;
        items.remove(0,rowCount);
        for( var i = 0;i < rowCount;i++ ) {
            var entry = myModel.get(i);
            if(entry.visible == true) {
                items.insert(entry, "visible");
            }
        }
    }
}
}
Persaud answered 27/11, 2018 at 13:33 Comment(0)
M
3
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Window 2.0

ApplicationWindow {
    width: 640
    height: 480
    visible: true
    property var model_items:[
        {id: 0,  _color: "red"     , _visible: true},
        {id: 1,  _color: "blue"    , _visible: false},
        {id: 2,  _color: "yellow"  , _visible: true},
        {id: 3,  _color: "gray"    , _visible: true},
    ]
    ListView {
        id: displayListView
        anchors.fill: parent
        model: myModel
        delegate: Rectangle{
            id: rec
            width: 200
            height: 200
            color: _color
        }
    }
    function createModel(){
        myModel.clear()
        for(var i=0;i<model_items.legth; i++)
            if(model_items[i]._visible)
                myModel.append(model_items[i])
    }

    ListModel {
        id: myModel
    }

    Component.onCompleted: {
        createModel()
    }
}
Malacostracan answered 10/4, 2019 at 9:9 Comment(0)
F
2

You can use QSortFilterProxyModel to filter values:

m_filterModel->setSourceModel(m_model);
Fortyfour answered 22/3, 2018 at 12:27 Comment(0)
C
1

This is a limitation of the the ListView that is still not resolved as of now. The solution is to either use another model for filtering (or adjust the current model) as suggested by other replies.

Or a better solution is to replace your ListView with a combination of

ScrollView { Column { Repeater {} } }

So instead of:

ListView {
    anchors.fill: parent

    model: ...
    delegate: ...
}

do:

ScrollView {
    anchors.fill: parent
    
    Column {
        Repeater {
            model: ...
            delegate: ...
        }
    }
}
Cystolith answered 9/2, 2021 at 15:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.