Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. ListView loaded by Loader directly causes sections to not update when model changed
Forum Updated to NodeBB v4.3 + New Features

ListView loaded by Loader directly causes sections to not update when model changed

Scheduled Pinned Locked Moved Solved QML and Qt Quick
2 Posts 1 Posters 216 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • fcarneyF Offline
    fcarneyF Offline
    fcarney
    wrote on last edited by fcarney
    #1

    Here is a "fun" one. I will be submitting a bug report:

    import QtQuick 2.15
    import QtQuick.Window 2.15
    import QtQuick.Controls 2.15
    
    Window {
        width: 640
        height: 480
        visible: true
        title: qsTr("ListView section header update")
    
        /*
            To cause the issue with sections not updating properly you need to scroll the list down a bit.
            listview1 not being inside an Item causes the problem
        */
    
        function makeEntry(name, param, value){
            let entry = {
                name: name,
                param: param,
                value_: value,
            }
    
            return entry
        }
    
        property var parammodel1: [
            makeEntry("name 1", "section 1", "1"),
            makeEntry("name 2", "section 1", "2"),
            makeEntry("name 3", "section 1", "3"),
            makeEntry("name 4", "section 2", "4"),
            makeEntry("name 5", "section 2", "5"),
            makeEntry("name 6", "section 3", "6"),
        ]
        property var parammodel2: [
            makeEntry("name 1", "section a", "1"),
            makeEntry("name 2", "section a", "2"),
            makeEntry("name 3", "section b", "3"),
            makeEntry("name 4", "section c", "4"),
            makeEntry("name 5", "section d", "5"),
            makeEntry("name 6", "section d", "6"),
        ]
    
        ListModel {
            id: parameters
    
            property var curmodel: parammodel1
            onCurmodelChanged: changeModel(curmodel)
    
            Component.onCompleted: {
                //changeModel(curmodel) // can cause crash, different bug...
            }
    
            function changeModel(modellist){
                clear()
                append(modellist)
            }
        }
    
        Rectangle {
            id: topitem
    
            anchors.top: parent.top
            width: parent.width
            height: 100
    
            border.width: 1
    
            Row {
    
                spacing: 20
    
                Text {
                    text: loader.item.objectName
                }
    
                Button {
                    text: "swap model"
    
                    onClicked: {
                        if(parameters.curmodel == parammodel1){
                            parameters.curmodel = parammodel2
                        }else{
                            parameters.curmodel = parammodel1
                        }
                    }
                }
    
                Button {
                    text: "change view"
    
                    onClicked: {
                        if(loader.sourceComponent == listview1_comp){
                            loader.sourceComponent = listview2_comp
                        }else{
                            loader.sourceComponent = listview1_comp
                        }
                    }
                }
            }
        }
    
        Loader {
            id: loader
    
            anchors.top: topitem.bottom
            anchors.bottom: parent.bottom
            width: parent.width / 2
    
            sourceComponent: listview1_comp
        }
    
        Component {
            id: listview1_comp
    
            //Item {
    
                ListView {
                    id: listview1
    
                    objectName: "listview1 broken"
    
                    visible: true
    
                    anchors.top: parent.top
                    anchors.bottom: parent.bottom
                    width: parent.width
    
                    model: parameters
    
                    currentIndex: 0
    
                    clip: true
    
                    highlightFollowsCurrentItem: true
                    snapMode: ListView.SnapToItem
                    highlightMoveDuration: 100
                    highlight: Rectangle {
                        z:10
                        color: "transparent"
                        border.width: 2
                        border.color: "yellow"
    
                        width: listview1.width
                        height: 30
                    }
    
                    highlightRangeMode: ListView.StrictlyEnforceRange
                    preferredHighlightBegin: 30
                    preferredHighlightEnd: 30 + 20
                    interactive: true
                    boundsBehavior: Flickable.StopAtBounds
    
                    reuseItems: false
                    cacheBuffer: 0
    
                    section.property: "param"
                    section.delegate: Rectangle {
                        width: listview1.width
                        height: 30
                        color: "lightgreen"
    
                        required property string section
    
                        Text {
                            text: section
                        }
                    }
    
                    delegate: Rectangle {
                        width: view.width
                        height: 30
    
                        property var view: ListView.view
    
                        Text {
                            text: "%1 = %2".arg(name).arg(value_)
                        }
    
                        MouseArea {
                            anchors.fill: parent
    
                            onClicked: {
                                view.currentIndex = index
                            }
                        }
                    }
                //}
            }
        }
    
        Component {
            id: listview2_comp
    
            Item {
                // if listview is not loaded directly by loader then it works fine
    
                objectName: "listview2 okay"
    
                ListView {
                    id: listview1
    
                    visible: true
    
                    anchors.top: parent.top
                    anchors.bottom: parent.bottom
                    width: parent.width
    
                    model: parameters
    
                    currentIndex: 0
    
                    clip: true
    
                    highlightFollowsCurrentItem: true
                    snapMode: ListView.SnapToItem
                    highlightMoveDuration: 100
                    highlight: Rectangle {
                        z:10
                        color: "transparent"
                        border.width: 2
                        border.color: "yellow"
    
                        width: listview1.width
                        height: 30
                    }
    
                    highlightRangeMode: ListView.StrictlyEnforceRange
                    preferredHighlightBegin: 30
                    preferredHighlightEnd: 30 + 20
                    interactive: true
                    boundsBehavior: Flickable.StopAtBounds
    
                    reuseItems: false
                    cacheBuffer: 0
    
                    section.property: "param"
                    section.delegate: Rectangle {
                        width: listview1.width
                        height: 30
                        color: "lightgreen"
    
                        required property string section
    
                        Text {
                            text: section
                        }
                    }
    
                    delegate: Rectangle {
                        width: view.width
                        height: 30
    
                        property var view: ListView.view
    
                        Text {
                            text: "%1 = %2".arg(name).arg(value_)
                        }
    
                        MouseArea {
                            anchors.fill: parent
    
                            onClicked: {
                                view.currentIndex = index
                            }
                        }
                    }
                }
            }
        }
    }
    

    Sorry for not explaining. When the underlying model changes on the listview then the sections can get corrupted. Particularly you have to scroll a bit. This only occurs on the listview not wrapped inside an Item that is loaded by a loader.

    C++ is a perfectly valid school of magic.

    1 Reply Last reply
    0
    • fcarneyF Offline
      fcarneyF Offline
      fcarney
      wrote on last edited by
      #2

      https://bugreports.qt.io/browse/QTBUG-103367

      C++ is a perfectly valid school of magic.

      1 Reply Last reply
      0

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved