BaddaBoompshhh
BaddaBoompshhh

Reputation: 55

Wordwrap on Text inside rectangle will not wrap using Qt QML

So I have been trying for weeks to simply get my text to wrap when it gets to to end of the rectangle. I have tried loads of things and this snippet is just the latest. Even if I use Layout ONLY and drop the "anchor" it does not do word wrapping, instead the text looks like the width is not set. Even if I force the rectangle and text width it just gets ignored.

var elem = '
    import QtQuick 2.15
    import QtQuick.Controls 2.15
    import QtQuick.Layouts 1.15

    RowLayout {
        id: rowlayout
        //anchors.fill: parent
        Layout.minimumHeight: 100
        Layout.preferredHeight: 100
        Layout.maximumHeight: 100
        spacing: 6
        Rectangle {
            id: element_one_rect
            color: "'+active+'"
            Layout.fillWidth: true
            Layout.minimumWidth: root.width * 0.25
            Layout.preferredWidth: root.width * 0.25
            Layout.maximumWidth: root.width * 0.25
            Layout.minimumHeight: 100
            Layout.margins: 10
            Text {
                anchors.centerIn: parent
                text: "'+description+'"
                color: "'+color+'"
                font.weight: Font.DemiBold
            }
        }
        Rectangle {
            color: "'+active+'"
            Layout.fillWidth: true
            Layout.minimumWidth: root.width * 0.72
            Layout.preferredWidth: root.width * 0.72
            Layout.preferredHeight: 100
            Layout.margins: 10
            Text {
                anchors.centerIn: parent
                text: "'+data+'"
                color: "'+color+'"
                font.weight: Font.Bold
                //wrapMode: Text.WordWrap
                wrapMode: Text.WrapAnywhere
            }
        }
    }';

Upvotes: 1

Views: 890

Answers (2)

Stephen Quan
Stephen Quan

Reputation: 26309

The problem as @LucaCarlon also indicated is that width has not been set. To demonstrate, look at the following minimal test:

    Rectangle {
        width: 250
        height: 250
        color: "grey"
        Text {
            text: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n"
            //width: 100
            //width: 200
            //width: 300
            //width: parent.width
            //wrapMode: Text.Wrap
            //wrapMode: Text.WordWrap
            //wrapMode: Text.WrapAnywhere
        }
    }

If you enable any of the wrapMode above but do not provide a width, you will observe the wrapMode is ignored. This makes sense because whilst it is willing to wrap, it doesn't know what to wrap to. Then, when you enable any of the width choices, you will suddenly observe that the word wrap will start working for you. Based on how your example reads, it seems that you are needing width: parent.width. This was also the conclusion that @LucaCarlon came to quite early on.

You can Try a demo online.

I also did a review of your code and came up with additional recommendations:

  1. Your code appears to be from a snippet that does code injection
    • I highly recommend against that, because it introduces security and performance problems
  2. Avoid using complex formula for Layout widths and heights
    • It's better to allow it to size things for you
    • If you use Layout.fillWidth with Layout.preferredWidth the RowLayout will allocate ratioed spacing for your components
  3. As per @GrecKo's suggestion of using Label instead of Text so you can use background and padding to stylize a frame and avoid unnecessary pixel calculations
  4. Also as per @GrecKo's suggestion use Text.Wrap which achieves a balance between Text.WordWrap and Text.WrapAnywhere

Here's a demonstration of the above:

import QtQuick
import QtQuick.Controls
import QtQuick.Layouts

Page {
    property string txt: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n"
    property color activeColor: "green"
    property color textColor: "white"
    RowLayout {
        id: rowlayout
        width: parent.width
        anchors.verticalCenter: parent.verticalCenter
        Label {
            Layout.fillWidth: true
            Layout.preferredWidth: 200
            background: Rectangle { color: activeColor }
            padding: 10
            text: txt
            color: textColor
            font.weight: Font.DemiBold
            wrapMode: Text.Wrap
        }
        Label {
            Layout.fillWidth: true
            Layout.preferredWidth: 400
            background: Rectangle { color: activeColor }
            padding: 10
            width: parent.width
            text: txt
            color: textColor
            font.weight: Font.Bold
            //wrapMode: Text.WordWrap
            //wrapMode: Text.WrapAnywhere
            wrapMode: Text.Wrap
        }
    }
}

You can Try it Online!

Upvotes: 0

Luca Carlon
Luca Carlon

Reputation: 9996

I would not expect the Text element to wrap without knowing its fixed size. So adding something like width: parent.width to your text element should make it wrap.

Upvotes: 2

Related Questions