rodrigob
rodrigob

Reputation: 2927

QML text scroll

I am using C++ and QML to create a nice interface. I would like to have a "console view", where plenty to text is printed through time. However, when the text of a text item or webview content grows, the view does not "scroll down".

How can I make the text on the bottom of the text/webview item always stay visible?

I have tried playing with flickable and the_webview.evaluateJavaScript + window.scrollTo , but I could not get them to do what I want. This seems a fairly simple piece of UI, but I am having serious troubles to do it with QML.

Upvotes: 5

Views: 9869

Answers (5)

RoachLin
RoachLin

Reputation: 37

After searching a lot, I think my code is concise enough to solve your problem:

Flickable {
    anchors.fill: parent
    contentWidth: this.width - scrollBar.width
    contentHeight: text.height
    flickableDirection: Flickable.VerticalFlick
    boundsBehavior: Flickable.StopAtBounds
    clip: true
    ScrollBar.vertical: ScrollBar {
        id: scrollBar
        policy: ScrollBar.AlwaysOn
    }

    Text {
        id: text
        anchors.centerIn: parent
        width: parent.width
        text: "long long text..."
        // textFormat: Text.MarkdownText
        wrapMode: Text.WordWrap
        color: "#3E3F42"
        // font.family: "Source Han Sans CN"
        font.weight: Font.Normal
        font.pixelSize: 22
        horizontalAlignment: Text.AlignLeft
        verticalAlignment: Text.AlignVCenter
    }
}

Upvotes: 0

kitizz
kitizz

Reputation: 91

My solution to this was to vertically flip both the content and Flickable. This way the text ends the right way up and is naturally anchored to the bottom of the flickable area.

It might be more efficient too since the transform is handled by OpenGL behind the scenes.

Flickable {
    id: flick
    anchors.fill: parent
    contentHeight: text.height
    Text {
        id: text
        width: parent.width
        transform: Scale { yScale: -1; origin.y: text.height/2 }
    }

    transform: Scale { yScale: -1; origin.y: flick.height/2 }
}

Upvotes: 1

rodrigob
rodrigob

Reputation: 2927

funkybro answers inspired my final solution:

function scroll_to_bottom() {
    flickabe_item.contentY = 
        Math.max(0, webview_item.height - flickabe_item.height);
    return;
}

Thanks !

Upvotes: 3

funkybro
funkybro

Reputation: 8671

Yeah I'd use a Flickable containing a Text object. Whenever you add text to the Text, check its paintedHeight, and adjust the Flickable's contentY if it's got any bigger.

Upvotes: 6

Ilkka
Ilkka

Reputation: 2694

Maybe you should consider using a ListView and have the messages as items in the view. Then you could use ListView::positionViewAtEnd.

Upvotes: 5

Related Questions