Qml文本换行(最大宽度)

时间:2011-06-14 14:30:00

标签: qt qml qt-quick

我想将文本放入气泡中,我希望我的气泡等于文字宽度,但如果文字长度太长,我希望文字自动换行并等于父宽度

此代码有效,但如果文本太长,则文本不会换行:

Rectangle {
    id:messageBoxCadre
    width: (modelData.messageLength>25)? (wrapper.width - 20): messageBox.width+10
    height: messageBox.height+5
    color: modelData.myMessage ? "#aa84b2":"#380c47"
    radius: 10

    Text {
        id:messageBox
        text: '<b><font color=purple>'+modelData.message+'</font></b> '
        wrapMode: "WordWrap"
    }
}

我尝试了这个文本换行,但是如果文本太小,则气泡宽度不等于文本大小:

Rectangle {
    id:messageBoxCadre
    width: (modelData.messageLength>25)? (wrapper.width - 20): messageBox.width+10
    height: messageBox.height+5
    color: modelData.myMessage ? "#aa84b2":"#380c47"
    radius: 10

    Text {
        id:messageBox
        width: (modelData.messageLength>25)? (wrapper.width - 20): messageBox.width
        text: '<b><font color=purple>'+modelData.message+'</font></b> '
        wrapMode: "WordWrap"
    }
}

7 个答案:

答案 0 :(得分:8)

你可以几乎与各州巧妙地做到这一点。问题是尝试通过将其分配给文本框的paintedWidth来设置父级的宽度意味着它然后设置文本框的宽度,QML将其检测为影响paintWidth。它不会比这更进一步,但QML仍然会发出警告。解决这个问题的一种方法是按照以下步骤操作,并有一个虚拟的不可见文本框,它可以解决文本应该有多宽的问题。它有点像黑客,但效果很好。

如果您更喜欢盒子宽度的像素限制,您可以将状态的“when”属性更改为依赖于虚拟文本框的大小(而不是字符串的长度)。

import QtQuick 1.0

Rectangle {
    id: containing_rect
    property string text

    text: "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat"
    //text: "a short string"

    Text {
        id: text_field
        anchors.top: parent.top
        anchors.left: parent.left

        height: parent.height
        width: parent.width
        text: parent.text
        wrapMode: Text.WordWrap

    }

    Text {
        id: dummy_text
        text: parent.text
        visible: false
    }

    states: [
            State {
                name: "wide text"
                when: containing_rect.text.length > 20
                PropertyChanges {
                    target: containing_rect
                    width: 200
                    height: text_field.paintedHeight
                }
            },
            State {
                name: "not wide text"
                when: containing_rect.text.length <= 20
                PropertyChanges {
                    target: containing_rect
                    width: dummy_text.paintedWidth
                    height: text_field.paintedHeight
                }
            }
        ]
}

答案 1 :(得分:4)

这是另一种使用Component.onCompleted脚本的方法。它比我的其他方法更静态,所以我想这取决于你想用它做什么。

import QtQuick 1.0

Rectangle {
    id: containing_rect
    property string text

    height: text_field.paintedHeight

    text: "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat"
    //text: "a short string"

    Text {
        id: text_field
        anchors.top: parent.top
        anchors.left: parent.left

        height: parent.height
        width: parent.width

        text: parent.text
        wrapMode: Text.WordWrap
    }

    Component.onCompleted: {
        if (text_field.paintedWidth > 200) {
            width = 200
        } else {
            width = text_field.paintedWidth
        }
    }     
}

答案 2 :(得分:2)

您也可以使用上面提到的虚拟文本框尝试这样的事情:

width: Math.min(dummy_text.paintedWidth, 250)

这将使用文本的绘制大小,除非它大于指定的像素宽度。

答案 3 :(得分:1)

试试这个:

Text {
    property int MAX_WIDTH: 400
    width: MAX_WIDTH
    onTextChanged: width = Math.min(MAX_WIDTH, paintedWidth)
}

答案 4 :(得分:1)

晚会很晚,但是干净的解决方案是使用嵌入式TextMetrics对象。像这样:

...
Text {
  id: textObj
  width: Math.min(textWidth, myThreshold)

  // access to binding-loop-free width and height:
  readonly property alias textWidth: textMetrics.boundingRect.width
  readonly property alias textHeight: textMetrics.boundingRect.height

  TextMetrics {
    id: textMetrics
    font: textObj.font
    text: textObj.text
    elide: textObj.elide
  }
}

答案 5 :(得分:0)

我没有使用状态,但我使用虚拟文本的想法来获得宽度。谢谢

我的代码:

                Rectangle{
                id:messageBoxCadre
                width: (modelData.messageLength>25)? (wrapper.width - 20): messageBox.width+10
                height: messageBox.height+5
                color: modelData.myMessage ? "#aa84b2":"#380c47"
                radius: 10

                Text {
                    id:messageBox
                    width: (modelData.messageLength>25)? (wrapper.width - 20): dummy_text.dummy_text
                    text: '<b><font color=purple>'+modelData.message+'</font></b> '
                    wrapMode: "WordWrap"
                }

                Text {
                      id: dummy_text
                      text: '<b><font color=purple>'+modelData.message+'</font></b> '
                      visible: false
                  }

            }

答案 6 :(得分:0)

显然已经晚了几年,但我遇到了类似的问题(虽然我使用的是elide而不是wrap,但基础知识是相同的)。我最终得到了一个简单而干净的解决方案,所以我想如果其他人遇到这个问题它可能会有所帮助。以原始代码为例:

        property int maxWidth: 100  // however you want to define the max width

        Rectangle{
            id:messageBoxCadre
            width: messageBox.paintedWidth+10  // width of the actual text, so your bubble will change to match the text width
            height: messageBox.height+5
            color: modelData.myMessage ? "#aa84b2":"#380c47"
            radius: 10

            Text {
                id:messageBox
                text: '<b><font color=purple>'+modelData.message+'</font></b> '
                width: maxWidth  // max width that your text can reach before wrapping
                wrapMode: "WordWrap"
            }
        }

这个例子的唯一问题是,使用WordWrap,如果一个单词太长而不适合Text项的整个宽度,它将超过你设置的maxWidth。