11
votes

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?

4
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?BaCaRoZzo
Good point! I did not think about it. Your answer covers it all. Thank you;)user2672883
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.GrecKo
And for information the similar question was this one : stackoverflow.com/questions/19207913/… I could swear the answer I commented on was working at the time, but it doesn't on my project :(GrecKo
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.user2672883

4 Answers

2
votes

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");
            }
        }
    }
}
}
2
votes
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()
    }
}
1
votes

You can use QSortFilterProxyModel to filter values:

m_filterModel->setSourceModel(m_model);
0
votes

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: ...
        }
    }
}