Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to programatically scroll a ScrollView to the bottom?

I've been trying to create a function that programmatically scrolls to bottom a ScrollView using Qt Quick Controls 2. I've tried various options, but much of the support I found online refers to Qt Quick Controls 1, not 2. This is what I've tried:

import QtQuick 2.8
import QtQuick.Controls 2.4

ScrollView {
    id: chatView

    anchors.top: parent.top
    anchors.left: parent.left
    anchors.right: parent.right
    anchors.bottom: inputTextAreaContainer.top

    function scrollToBottom() {
        // Try #1
//      chatView.contentItem.contentY = chatBox.height - chatView.contentItem.height
//      console.log(chatView.contentItem.contentY)

        // Try #2
//      flickableItem.contentY = flickableItem.contentHeight / 2 - height / 2
//      flickableItem.contentX = flickableItem.contentWidth / 2 - width / 2

        // Try #3
        chatView.ScrollBar.position = 0.0 // Tried also with 1.0
    }

    TextArea {
        id: chatBox
        anchors.fill: parent
        textFormat: TextArea.RichText
        onTextChanged: {
            // Here I need to scroll
            chatView.scrollToBottom()
        }
    }
}

Does anyone know how this can be achieved using Qt Quick Controls 2? If no, does anyone have any alternatives to this approach?

like image 505
Jacob Krieg Avatar asked Jun 16 '26 20:06

Jacob Krieg


1 Answers

Cause

You are trying to set the ScrollBar's position to 1.0:

chatView.ScrollBar.position = 0.0 // Tried also with 1.0

however, you do not consider its size.

Solution

Take into account the size of the ScrollBar when you set its position like this:

chatView.ScrollBar.vertical.position = 1.0 - chatView.ScrollBar.vertical.size

How I came up with this solution?

I was curious of how Qt itself solves this problem, so I took a look at how QQuickScrollBar::increase() is implemented and I saw this line:

setPosition(qMin<qreal>(1.0 - d->size, d->position + step));

Then I took the first argument of qMin, i.e. 1.0 - d->size, and the solution was clear.

Example

Since you did not provide a MCE, I wrote one myself. I hope you can adapt it for your particullar case. Here it is:

import QtQuick 2.8
import QtQuick.Controls 2.4
import QtQuick.Layouts 1.12

ApplicationWindow {
    width: 480
    height: 640
    visible: true
    title: qsTr("Scroll To Bottom")

    ColumnLayout {
        anchors.fill: parent

        ScrollView {
            id: scrollView

            Layout.fillWidth: true
            Layout.fillHeight: true

            function scrollToBottom() {
                ScrollBar.vertical.position = 1.0 - ScrollBar.vertical.size
            }

            contentWidth: children.implicitWidth
            contentHeight: children.implicitHeight
            ScrollBar.vertical.policy: ScrollBar.AlwaysOn
            clip: true

            ColumnLayout {

                Layout.fillWidth: true
                Layout.fillHeight: true

                Repeater {
                    model: 50

                    Label {
                        text: "Message: " + index
                    }
                }
            }
        }

        TextField {
            Layout.fillWidth: true
        }
    }

    Component.onCompleted: {
        scrollView.scrollToBottom()
    }
}

Result

The example produces the following result:

Window with a list, scrolled to the bottom

like image 124
scopchanov Avatar answered Jun 19 '26 12:06

scopchanov