17

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

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

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"
    }
}
4

7 回答 7

10

几乎可以用状态巧妙地做到这一点。问题是试图通过将父级的宽度分配给文本框的paintWidth 来设置父级的宽度意味着它会设置文本框的宽度,QML 检测到该宽度会影响paintedWidth。它不会比这更进一步,但 QML 仍然会发出警告。解决该问题的一种方法是执行以下操作,并使用一个虚拟的不可见文本框来计算文本的宽度/应该有多宽。它有点hack,但效果很好。

如果您希望对框的宽度进行像素限制,则可以将状态的“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
                }
            }
        ]
}
于 2011-06-15T08:37:26.307 回答
5

这是另一种方式,它使用 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
        }
    }     
}
于 2011-06-15T09:26:10.090 回答
3

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

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

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

于 2011-08-30T15:19:43.857 回答
3

聚会很晚,但干净的解决方案是使用嵌入式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
  }
}
于 2020-08-18T15:45:14.997 回答
2

尝试这个:

Text {
    property int MAX_WIDTH: 400
    width: MAX_WIDTH
    onTextChanged: width = Math.min(MAX_WIDTH, paintedWidth)
}
于 2012-11-26T18:31:27.353 回答
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
                  }

            }
于 2011-06-15T12:08:19.130 回答
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。

于 2014-06-05T16:25:23.330 回答