Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct

    Unsolved Connect custom Scrollbar and Flickable

    QML and Qt Quick
    1
    1
    73
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • F
      fryn3 last edited by

      I have a virtual large table, and an area that is real drawn. Depending on the position of the content, a certain part of the virtual table is displayed.
      And now I'm trying in different ways to synchronize the content and the scrollbar.
      In this case, the scrollbar jumps with the content.

      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
                          }
                      }
                  }
              }
          }
      }
      

      performance

      Error when I try to drag the canvas
      error

      1 Reply Last reply Reply Quote 0
      • First post
        Last post