Прокрутка двух или более списков в 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, работающий в абсолютном режиме, всегда будет прокручивать одинаковое количество пикселей независимо от размера контента, который удобно там, где требуется точность.