Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

ScrollBar not working properly with ListView when delegates are hidden



  • Hello, my application uses a list with QObjects as a ListView model. Depending on the data in said QObjects, some delegates are hidden. This means the properties enabled and visible is set to false, height is set to 0.
    When scrolling, the scroll bar changes size depending on the current position of the list. Are there other scroll bar implementations which can handle hidden list elements?
    ezgif.com-optimize.gif

                ListView {
                  
                    id:errWarnListId             
                    model: backend.errWarnList
    
                    delegate: delegateErrWarn
                    ScrollBar.vertical: ScrollBar {
                        policy: ScrollBar.AsNeeded
                    }
                }
    
    
                Component{
                    id: delegateErrWarn             
                  
                    ErrWarnPanel {
                        id: errWarnPanel
                       
                        enabled: modelData.active
                        visible: modelData.active
                        width:errWarnListId.width
                        height:         modelData.active?75:0
                        active:         modelData.active
                        signalName:     "id"//modelData.id
                        comment:        "comment"//modelData.comment
                        faultType:      1//modelData.errWarnType
                        errGroup:       "group"//modelData.errGroup
                    }
                }
    

  • Moderators

    hi @bozo

    I ran into that as well, sadly, there's no way I found to fix this inside a ListView itself.

    But, let me tell you about my work around

    I replaced ListView with a Flickable, and a Column + Repeater as the content and added manually a Scrollbar to it, as an additional item

    Inside the Scrollbar item, I added a function, named, recalculatingSize that defines the actual hight of the Scrollbar

    //view is the Id of the flickable
    ScrollBar{
            id: scroll
            anchors.right: parent.right
    
            height: view.height
           onHeightChanged: scroll.recalculateSize()
            width: view.maxHeight > view.height ? 50 : 0
            Behavior on width {NumberAnimation{duration: 50}}
    
            active: true
            Component.onCompleted: scroll.recalculateSize()
    
            function recalculateSize(){
                size = view.height / view.maxHeight
            }
    
            Connections{
                target: view
                onContentYChanged: if(!scroll.pressed)scroll.position = view.contentY / view.maxHeight
            }
    
            onPositionChanged:{
                recalculateSize()
                view.contentY = view.maxHeight * position
            }
        }
    

    the maxHeight is the magical property, where you have to calculate and define the actually current(accumulated) height of your visible items

    property real maxHeight: numberOfVisibleItems * itemHeight + spacings //etc
    //important to bind the contentHeight of the Flickable to the maxHeight
    contentHeight: maxHeight
    


  • Hi @J-Hilk ,
    thanks for the reply. I tried your solution and it works for the most part. One thing making trouble now is the decelleration of the list. When the scroll bar is enabled, the list just stops once you stop scrolling. Without the scroll bar it slowly decellerates. Also when the list is dragged out of bounds, it does not return automatically. It needs to be dragged back manually.


  • Qt Champions 2018

    Hiding delegates is not the proper solution and it has performance drawbacks.

    What you need is a proper QAbstractListModel (your own or from http://gitlab.unique-conception.org/qt-qml-tricks/qt-qml-models maybe), and a QSortFilterProxyModel to filter your source model.


Log in to reply