Remember the scroll position in a QML element

I have some qml that acts as the result of an application (sort of like a read-only console). However, this is annoying because when you print information, it scrolls back.

For example, let's say I print a line on TextArea every second, after a minute or so, I will have enough lines that now have a scroll bar. I scroll to the bottom, after a second a line of text is printed, causing it to scroll backward.

The desired functionality that I would like is to automatically scroll it down (just like the console when it prints material) if the user does not override it by scrolling the text and then the text should remain in place. Hope this made sense, here is some code:

  ScrollArea { id: helpTextScrollArea anchors.left: parent.left anchors.right: parent.right anchors.top: myButton.bottom anchors.topMargin: 5 anchors.bottom: parent.bottom visible: false horizontalScrollBar.visible: false onVisibleChanged: { helpText.visible = visible } HelpTextArea { id: helpText width: parent.parent.width - helpTextScrollArea.verticalScrollBar.width text: "Oops, no documentation." onVisibleChanged: { if(helpTextScrollArea.visible != visible) { helpTextScrollArea.visible = visible } } } } Flickable { id: flick anchors.left: parent.left anchors.right: parent.right anchors.top: runStopButton.bottom anchors.bottom: parent.bottom anchors.topMargin: 5 TextArea{ id: messageArea anchors.fill: parent focus: true readOnly: true visible: !helpTextScrollArea.visible wrapMode: TextEdit.Wrap function addText(newText) { text += newText + "\n" } } } 

Note. I don’t think my Flickable does anything, it was part of my experiment to fix this problem. In addition, I use the addText function to print in the text area. I know almost nothing about qml, and most of this code was written by someone else, and I'm trying to work with it. Thanks!

+6
source share
3 answers

You can bind the contentY property to Flickable to an expression that will calculate the correct position.

 Flickable { id: flick states: State { name: "autoscroll" PropertyChanges { target: flick contentY: messageArea.height - height } } onMovementEnded: { if (contentY === messageArea.height - height) { state = "autoscroll" } else { state = "" // default state } } // ... } 
+3
source

Flickable has 4 readonly properties in the name of visibleArea. * (you can read their meaning in the QML documentation):

  • visibleArea.xPosition : xPosition = contentX / contentWidth
  • visibleArea.yPosition : yPosition = contentY / contentHeight
  • visibleArea.widthRatio : widthRatio = width / contentWidth
  • visibleArea.heightRatio : heightRatio = height / contentHeight
+2
source

If you use GridView instead of Flickable, you can use these methods.

 positionViewAtBeginning() positionViewAtEnd() positionViewAtIndex(int index, PositionMode mode) 

I found that they are really useful, because when adding a line of text, just call the positionViewAtEnd() method inside the GridView .

Hope this helps

0
source

Source: https://habr.com/ru/post/917443/


All Articles