【发布时间】:2021-07-21 11:55:26
【问题描述】:
我有一个虚拟的大桌子和一个真实绘制的区域。根据内容的位置,显示虚拟表的某个部分。 现在我正在尝试以不同的方式来同步内容和滚动条。 在这种情况下,滚动条会随内容一起跳动。
AreaScrollBar.qml
import QtQuick 2.15
import QtQuick.Controls 2.15
ScrollBar {
id: root
/// Virtual content size
/// 50000
property real virtualContentSize: 0
/// Real content size
/// 2000
property real contentSize: 0
/// Visible content size
/// 500
property real visibleSize: orientation === Qt.Horizontal ? width : height
/// Position offset step.
/// 100
property real stepAreaPosition: 1
/// The position of the component area [0 .. virtualContentSize - contentSize]
property real areaPosition: 0
/// [0 .. contentSize - visibleSize]
property real positionInArea: 0
property QtObject priv: QtObject {
/// В запасе после перестроения
readonly property real buffer: 0.2 * contentSize - (0.2 * contentSize) % stepAreaPosition
}
size: (orientation === Qt.Horizontal ? width : height) / virtualContentSize
policy: ScrollBar.AlwaysOn
onPositionChanged: {
console.log('onPosChanged', position)
let arP = -1
let pia = -1
if (position < 0) {
position = 0
} else if (position + size > 1) {
position = 1 - size
}
if (position * virtualContentSize + visibleSize
> areaPosition + 0.9 * contentSize) {
pia = priv.buffer
} else if (position * virtualContentSize - areaPosition < 0.1 * contentSize) {
pia = contentSize - (priv.buffer + visibleSize)
} else {
positionInArea = position * virtualContentSize - areaPosition
return
}
arP = position * virtualContentSize - pia
let arp2 = 0
if (arP < 0) {
arp2 = 0
} else if (arP > virtualContentSize - contentSize) {
arp2 = virtualContentSize - contentSize
} else {
arp2 = arP - (arP % stepAreaPosition)
}
positionInArea = position * virtualContentSize - arp2
areaPosition = arp2
}
}
main.qml
import QtQuick 2.15
import QtQuick.Window 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
Window {
width: 600
height: 600
visible: true
title: qsTr("Hello World")
Column {
focus: true
Keys.onDownPressed: vSb.position += 10 / vSb.virtualContentSize
Keys.onUpPressed: vSb.position -= 10 / vSb.virtualContentSize
Keys.onLeftPressed: hSb.position -= 10 / hSb.virtualContentSize
Keys.onRightPressed: hSb.position += 10 / hSb.virtualContentSize
Row {
Column {
Text { text: qsTr("vSb.position %1").arg(vSb.position) }
Text { text: qsTr("vSb.areaPosition %1").arg(vSb.areaPosition) }
Text { text: qsTr("vSb.positionInArea %1").arg(vSb.positionInArea) }
}
Item {
width: 100
height: 1
}
Column {
Text { text: qsTr("hSb.position %1").arg(hSb.position) }
Text { text: qsTr("hSb.areaPosition %1").arg(hSb.areaPosition) }
Text { text: qsTr("hSb.positionInArea %1").arg(hSb.positionInArea) }
}
}
Rectangle {
id: mainArea
width: 500
height: 500
clip: true
color: "gray"
border.color: "darkgray"
border.width: 3
property int _rows: 50
property int _columns: 10
property int _virtualRows: 500
property int _virtualColumns: 50
property int _rectWidth: 90
property int _rectHeight: 90
property int _spacing: 10
property int _virtualContentWidth: _virtualColumns * (_rectWidth + _spacing)
property int _virtualContentHeight: _virtualRows * (_rectHeight + _spacing)
Flickable {
id: _flick
anchors.fill: parent
contentWidth: mainArea._columns * (mainArea._rectWidth + mainArea._spacing)
contentHeight: mainArea._rows * (mainArea._rectHeight + mainArea._spacing)
Column {
spacing: mainArea._spacing
Repeater {
model: mainArea._rows
Row {
property int rowInd: index
spacing: mainArea._spacing
Repeater {
model: mainArea._columns
Rectangle {
id: rect
property int columnInd: index
width: mainArea._rectWidth
height: mainArea._rectHeight
color: "#3c324a"
Column {
Repeater {
model: rect.height / 10
Rectangle {
width: rect.width
height: 10
color: Qt.lighter(rect.color, 1 + index * 0.1)
}
}
}
Text {
anchors.fill: parent
horizontalAlignment: Text.AlignLeft
verticalAlignment: Text.AlignTop
text: '[%2, %3]'.arg(rowInd).arg(columnInd)
font.pointSize: 7
}
Text {
anchors.fill: parent
horizontalAlignment: Text.AlignHCenter
verticalAlignment: Text.AlignVCenter
text: ('content\n[%1, %2]'
.arg(vSb.areaPosition / vSb.stepAreaPosition + rowInd)
.arg(hSb.areaPosition / hSb.stepAreaPosition + columnInd))
font.pixelSize: 15
}
}
}
}
}
}
interactive: true
Binding on contentX {
value: {
console.log('_flick.contentX', _flick.contentX, hSb.positionInArea)
return hSb.positionInArea
}
}
Binding on contentY {
value: {
console.log('_flick.contentY', _flick.contentY, vSb.positionInArea)
return vSb.positionInArea
}
}
}
AreaScrollBar {
id: vSb
orientation: Qt.Vertical
stepAreaPosition: mainArea._rectHeight + mainArea._spacing
virtualContentSize: mainArea._virtualRows * stepAreaPosition
contentSize: mainArea._rows * stepAreaPosition
anchors.top: parent.top
anchors.right: parent.right
anchors.bottom: hSb.top
Binding on position {
value: {
console.log('vSb.position', _flick.contentY,
vSb.areaPosition, vSb.virtualContentSize)
return (_flick.contentY + vSb.areaPosition) / vSb.virtualContentSize
}
}
}
AreaScrollBar {
id: hSb
orientation: Qt.Horizontal
stepAreaPosition: mainArea._rectWidth + mainArea._spacing
virtualContentSize: mainArea._virtualColumns * stepAreaPosition
visibleSize: mainArea.width
anchors.bottom: parent.bottom
anchors.left: parent.left
anchors.right: vSb.left
Binding on position {
value: {
console.log('hSb.position', _flick.contentX,
hSb.areaPosition, hSb.virtualContentSize)
return (_flick.contentX + hSb.areaPosition) / hSb.virtualContentSize
}
}
}
}
}
}
【问题讨论】:
-
抱歉,我不明白,您希望这段代码以其他方式工作吗?
-
现在滚动条跳跃
-
哦,是的。现在我明白了。