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?

BaCaRoZzo
  • 7,502
  • 6
  • 51
  • 82
user2672883
  • 141
  • 1
  • 6
  • What's bad about `height: model.visible ? 30 : 0` ? – BaCaRoZzo Sep 08 '15 at 09:51
  • 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. – user2672883 Sep 08 '15 at 09:59
  • 6
    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 Sep 08 '15 at 10:05
  • 1
    Good point! I did not think about it. Your answer covers it all. Thank you;) – user2672883 Sep 08 '15 at 10:23
  • @BaCaRoZzo, wanna answer this so we can see that it's solved? :) – Mitch Sep 10 '15 at 06:29
  • @Mitch 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. – BaCaRoZzo Sep 10 '15 at 10:32
  • @BaCaRoZzo no idea. :p – Mitch Sep 10 '15 at 10:32
  • @Mitch lighting fast... :D k, I'm going to search for that. – BaCaRoZzo Sep 10 '15 at 10:35
  • 1
    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 Sep 10 '15 at 10:38
  • 1
    And for information the similar question was this one : http://stackoverflow.com/questions/19207913/removing-empty-spaces-when-the-delegate-is-not-visible-in-a-gridview/ I could swear the answer I commented on was working at the time, but it doesn't on my project :( – GrecKo Sep 10 '15 at 10:40
  • @GrecKo 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. – BaCaRoZzo Sep 10 '15 at 15:25
  • 1
    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 Sep 14 '15 at 08:35
  • @GrecKo I've played around with `ListView` a little bit. Using `Loader`s does not help either. Now, if you remove the hack in [this example](http://pastebin.com/embed_js.php?i=LPh32ewh) 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. – BaCaRoZzo Sep 17 '15 at 14:43
  • @BaCaRoZzo I don't understand what you are trying to show in your example – GrecKo Sep 17 '15 at 14:49
  • Sorry. I was just asking myself if It was more a wrong scrolling behaviour than an actual performance issue. Uhm, probably a stupid guessing. :) – BaCaRoZzo Sep 17 '15 at 14:57
  • Thanks, this issue answered my question. – Edip Ahmet Feb 04 '18 at 15:21
  • Does this answer your question? [Hide an item (delegate) inside a ListView QML](https://stackoverflow.com/questions/48565082/hide-an-item-delegate-inside-a-listview-qml) – ניר Jun 09 '22 at 20:01

4 Answers4

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");
            }
        }
    }
}
}
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()
    }
}
Pham Thanh
  • 27
  • 2
2

You can use QSortFilterProxyModel to filter values:

m_filterModel->setSourceModel(m_model);
alez
  • 69
  • 7
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: ...
        }
    }
}
Mahmoud Badri
  • 1,256
  • 14
  • 24