Прокрутка двух или более списков в QML

Мне нужно прокрутить два или более списка одновременно, используя одну полосу прокрутки. Изначально я использовал Column внутри Flickable но свиток происходил не так, как ожидалось. Позже я использовал ListView и даже это не было правильно прокручивать.

Итак, как прокрутить элемент содержимого списка / макета с помощью полосы прокрутки? Должен ли я использовать ScrollView или же Flickable или что-то другое?

Пример моего интерфейса

2 ответа

Решение

Вы могли бы просто использовать Flickable с вашим Columns, Я не знаю как твои Columns расположены горизонтально, но если они находятся внутри Row это довольно просто:

import QtQuick 2.7
import QtQuick.Controls 2.0

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Multi Column")

    Flickable {
        anchors.fill: parent
        contentWidth: row.implicitWidth
        contentHeight: row.implicitHeight
        Row {
            id: row
            Column {
                spacing: 5
                Repeater {
                    model: 20
                    delegate: Rectangle {
                        width: 50
                        height: 50
                        color: "red"
                        Text {
                            anchors.centerIn: parent
                            text: index
                        }
                    }
                }
            }
            Column {
                spacing: 5
                Repeater {
                    model: 30
                    delegate: Rectangle {
                        width: 50
                        height: 50
                        color: "cyan"
                        Text {
                            anchors.centerIn: parent
                            text: index
                        }
                    }
                }
            }
        }
        ScrollBar.vertical: ScrollBar { }
    }
}

Даже если они не в Row Вы могли бы сделать:
contentHeight: Math.max(column1.height, column2.height, ...)

Демонстрация:
Прокрутка нескольких столбцов

Стандартная полоса прокрутки будет привязана только к одному прокручиваемому элементу. Тем не менее, легко создать пользовательский скроллер и подключить к нему несколько представлений:

  Row {
    Flickable {
      width: 50
      height: main.height
      contentHeight: contentItem.childrenRect.height
      interactive: false
      contentY: (contentHeight - height) * scroller.position
      Column {
        spacing: 5
        Repeater {
          model: 20
          delegate: Rectangle {
            width: 50
            height: 50
            color: "red"
            Text {
              anchors.centerIn: parent
              text: index
            }
          }
        }
      }
    }
    Flickable {
      width: 50
      height: main.height
      contentHeight: contentItem.childrenRect.height
      interactive: false
      contentY: (contentHeight - height) * scroller.position
      Column {
        spacing: 5
        Repeater {
          model: 30
          delegate: Rectangle {
            width: 50
            height: 50
            color: "cyan"
            Text {
              anchors.centerIn: parent
              text: index
            }
          }
        }
      }
    }
    Rectangle {
      id: scroller
      width: 50
      height: 50
      color: "grey"
      property real position: y / (main.height - 50)
      MouseArea {
        anchors.fill: parent
        drag.target: parent
        drag.minimumY: 0
        drag.maximumY: main.height - 50
        drag.axis: Drag.YAxis
      }
    }
  }

Обратите внимание, что он будет работать адекватно, даже если представления имеют разную высоту содержимого, прокручивая каждое представление относительно положения прокрутки:

введите описание изображения здесь

Понимая, что вопрос был поставлен не так хорошо, просто на тот случай, если кто-то захочет прокрутить несколько видов одновременно, я, тем не менее, поделюсь другим интересным подходом, похожим на джог-джойстик, который может двигаться бесконечно во всех направлениях, а не иметь ограниченный диапазон, как полоса прокрутки. Это решение будет прокручивать два представления синхронно, пока они не достигнут диапазона своих диапазонов. В отличие от ответа GrecKo, это никогда не оставляет вас "пустым представлением", когда размер представления отличается:

введите описание изображения здесь

  Row {
    Flickable {
      id: f1
      width: 50
      height: main.height
      contentHeight: contentItem.childrenRect.height
      interactive: false
      Connections {
        target: jogger
        onScroll: f1.contentY = Math.max(0, Math.min(f1.contentHeight - f1.height, f1.contentY + p))
      }
      Column {
        spacing: 5
        Repeater {
          model: 20
          delegate: Rectangle {
            width: 50
            height: 50
            color: "red"
            Text {
              anchors.centerIn: parent
              text: index
            }
          }
        }
      }
    }
    Flickable {
      id: f2
      width: 50
      height: main.height
      contentHeight: contentItem.childrenRect.height
      interactive: false
      Connections {
        target: jogger
        onScroll: f2.contentY = Math.max(0, Math.min(f2.contentHeight - f2.height, f2.contentY + p))
      }
      Column {
        spacing: 5
        Repeater {
          model: 30
          delegate: Rectangle {
            width: 50
            height: 50
            color: "cyan"
            Text {
              anchors.centerIn: parent
              text: index
            }
          }
        }
      }
    }
    MouseArea {
      id: jogger
      width: 50
      height: main.height
      drag.target: knob
      drag.minimumY: 0
      drag.maximumY: main.height - 50
      drag.axis: Drag.YAxis
      signal scroll(real p)
      property real dy: 0
      onPressed: dy = mouseY
      onPositionChanged: {
        scroll(dy - mouseY)
        dy = mouseY
      }
      onScroll: console.log(p)
      Rectangle {
        anchors.fill: parent
        color: "lightgrey"
      }
      Rectangle {
        id: knob
        visible: parent.pressed
        width: 50
        height: 50
        color: "grey"
        y: Math.max(0, Math.min(parent.mouseY - 25, parent.height - height))
      }
    }
  }

Еще одно преимущество подхода "пробежки" заключается в том, что он не относительный, а абсолютный. Это означает, что если ваш вид огромен, если вы используете скроллер, то даже один пиксель может привести к значительному сдвигу в контенте, тогда как Jog, работающий в абсолютном режиме, всегда будет прокручивать одинаковое количество пикселей независимо от размера контента, который удобно там, где требуется точность.

Другие вопросы по тегам