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

Scroll bar behaves unexpectedly in TableView 2.0



  • I implemented some filtering in my TableView 2.0 with a custom table model that calls beginInsertRows/endInsertRows and beginRemoveRows/endRemoveRows and I was surprised that basically it works along with the sorting excluding some details that I already mentioned in my previous post.

    When TableView displays the first rows, it is not notable that filtering results in incorrect scroll indicator size and placement, see the video.

    But if I scroll to the last row and than apply a filter, scroll bar starts to behave unexpectedly (at the end of the video).

    I checked in the debugger, the model's rowCount() function returns 6 rows when I press 'RUB' button and its more likely that the model works correctly.

    I am not sure, but I have an impression that there can be some timeout, that prevents the scroll bar from being updated. Is it possible?

    EDIT1: After doing some further experimentation I realized that the scroll bar simply is not updated when the number of rows is changed (independently of the content position).

    EDIT2 It is a really annoying glitch, see another video. I select 'favorite' items and then filter the table by 'favorite' flag.

    QML code of TableView:

        TableView {
            id: table
            anchors.fill: parent
            columnSpacing: 5
            rowSpacing: 3
            clip: true
    
            property var columnWidths: [100, 80, 80, 120];
            columnWidthProvider: function (column) { return columnWidths[column]; }
    
            property var rowHeight: 40
    
            rowHeightProvider: function (column) { return rowHeight; }
    
            ScrollBar.horizontal: ScrollBar{}
            ScrollBar.vertical: ScrollBar{}
            ScrollIndicator.horizontal: ScrollIndicator { }
            ScrollIndicator.vertical: ScrollIndicator { }
    
            MouseArea
            {
                id: ma
                anchors.fill: parent
                hoverEnabled: true
                onClicked: {
                    var index = Math.floor(mouse.y / (table.rowHeight + table.rowSpacing));
                    console.log(index, " ", mouse.x, " ", mouse.y, " ", table.contentX, " ", table.contentY)
                    var item = table.model.rowKey(index)
                    window.openMarket(item)
                }
            }
    
            delegate: DelegateChooser {
                role: "type"
                DelegateChoice {
                    roleValue: "symbol"
                    delegate: SymbolCell { item: model.item }
                }
                DelegateChoice {
                    roleValue: "price"
                    delegate: Text {
                        horizontalAlignment: Text.AlignRight
                        verticalAlignment: Text.AlignVCenter
                        text: { var val = model.item[model.name]; return val ? val.toFixed(model.item.pricePrecision) : ""; }
                    }
                }
                DelegateChoice {
                    roleValue: "signal"
                    delegate: Text {
                        horizontalAlignment: Text.AlignRight
                        verticalAlignment: Text.AlignVCenter
                        text: TimeFormat.ago(model.item.signalTime, timeMachine.now)
                        color: model.item.signalTime ? "black" : "gray"
                    }
                }
                DelegateChoice {
                    delegate: Text {
                        verticalAlignment: Text.AlignVCenter
                        text: model.item[model.name]
                    }
                }
            }
        }
    

    EDIT3: If I call forceLayout() after applying the filter it works a bit better, but still unexpectedly, see the video. The scroll bar is updated, but the rows are moved outside of the visible area and I make it visible with the mouse wheel. To make forceLayout() work a bit more expectedly I used the following code:

        function forceLayoutWorkaround()
        {
            table.forceLayout()
    
            var zero_y = table.contentHeight - table.height
    
            if (table.contentY > zero_y)
            {
                table.contentY = zero_y < 0 ? 0 : zero_y
            }
        }
    

    but still it is not clear what to do if the filter applied dynamically when a row is changed.


Log in to reply