Поведение QML ListView по умолчанию при обновлении модели - PullRequest
0 голосов
/ 19 июня 2019

У меня есть следующее ListView, которое всегда показывает начало списка, когда QStringListModel обновляется с помощью setStringList на стороне C ++.

Например, пользователь может прокручивать вверх и вниз в представлении, а когда модель обновляется, представление возвращается к началу списка.

Как отключить это поведение?

Также мне нужно, чтобы представление отображало ровно X элементов (2 в моем примере) одновременно.Представление не прокручивается само по себе (interactive: false), но пользователь может перемещаться по списку, нажимая вверх и вниз по Button где-то в пользовательском интерфейсе.

Есть ли подходящий подход для этого?(следующий Можно ли показывать только определенные индексы списка QML? )

РЕДАКТИРОВАТЬ: я добавил 2 функции для задачи «вверх / вниз» иКажется, он работает, как ожидалось, но мне все еще интересно узнать, есть ли лучший способ.

Спасибо.

        ListView {
            id: view
            anchors.top = parent.top
            anchors.left = parent.left
            readonly property int visibleItems: 2
            readonly property int itemHeight: 20
            height: visibleItems * itemHeight
            width: 100
            clip: true

            model: listModel // a QStringListModel

            delegate: Rectangle {
                border.width: 1
                border.color: "black"
                height: view.itemHeight
                width: 100
                Text { text: model.display }
            }

            interactive: false

            function up() {
                var currentTopIndex =  indexAt(view.width / 2, contentY)

                if (currentTopIndex !== -1) {

                    var newTopIndex = currentTopIndex - view.visibleItems

                    if (newTopIndex >= 0)
                        view.positionViewAtIndex(newTopIndex, ListView.Beginning)
                 }
            }

            function down() {
                var currentTopIndex =  indexAt(view.width / 2, contentY)

                if (currentTopIndex !== -1) {

                    var newTopIndex = currentTopIndex + view.visibleItems

                    if (newTopIndex < view.count)
                        view.positionViewAtIndex(newTopIndex, ListView.Beginning)
                 }
            }

Ответы [ 2 ]

1 голос
/ 19 июня 2019

Добавьте это внутри ListView, при каждом изменении данных модели вы сбрасываете свойство contentY.Здесь я предполагаю, что contentX не меняется.

property real previousContentY

Connections {
    target: model
    onModelAboutToBeReset: view.previousContentY = view.contentY
    onModelReset: view.contentY = view.previousContentY
}

И вы, вероятно, также хотите добавить snapMode: ListView.SnapToItem, если хотите показать только определенные элементы.

0 голосов
/ 20 июня 2019

Решением может быть обтекание ListView внешним Flickable, который будет отвечать за прокрутку.

Это решение не требует ручного сброса предыдущего ListView contentY, поскольку положение прокрутки больше не зависит от самого ListView.

Вот основной рабочий пример:

Button {
    id: button
    text: 'change model'
    onClicked: view.aModel = !view.aModel
}

Flickable {
    anchors.top: button.bottom
    width: parent.width
    height: 100
    interactive: true // the scroll will be managed by this external Flickable
    contentHeight: view.contentHeight
    clip: true

    ListView {
        id: view
        property bool aModel: true
        anchors.fill: parent
        interactive: false // deactivate scroll on the internal Flickable
        model: aModel
               ? ["a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a", "a"]
               : ["b", "b", "b", "b", "b", "b", "b", "b", "b", "b", "b", "b", "b", "b"]
        delegate: Text {
            width: parent.width
            height: 20
            text: modelData + index
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...