Обтекание текстом Qml (максимальная ширина) - PullRequest
12 голосов
/ 14 июня 2011

Я хотел бы поместить текст в пузырь, и я хочу, чтобы мой пузырь был равен ширине текста, но если длина текста слишком велика, я бы хотел, чтобы текст автоматически переносился и был равен ширине родителя..

Этот код работает, но текст не переносится, если текст слишком длинный:

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

Ответы [ 6 ]

8 голосов
/ 15 июня 2011

Вы можете почти делать это аккуратно с состояниями. Проблема заключается в том, что попытка установить ширину родительского элемента путем присвоения его закрашенной ширине текстового поля означает, что он затем устанавливает ширину текстового поля, которое QML обнаруживает как влияющее на paintWidth. Это не будет повторяться дальше, чем это, но QML по-прежнему выдает предупреждения. Одним из способов решения этой проблемы является следующее: наличие фиктивного невидимого текстового поля, которое просто определяет, насколько широким должен быть текст. Это что-то вроде взлома, но работает хорошо.

Вы можете изменить свойство «когда» состояния, чтобы оно зависело от размера фиктивного текстового поля (а не от длины строки), если вы предпочитаете ограничение в пикселях для ширины поля.

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
                }
            }
        ]
}
4 голосов
/ 15 июня 2011

Вот еще один способ, который использует скрипт 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 голосов
/ 30 августа 2011

Вы также можете попробовать что-то подобное, используя пустое текстовое поле, упомянутое выше:

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

При этом будет использоваться окрашенный размер текста, если он не превышает заданную вами ширину в пикселях.

1 голос
/ 26 ноября 2012

Попробуйте это:

Text {
    property int MAX_WIDTH: 400
    width: MAX_WIDTH
    onTextChanged: width = Math.min(MAX_WIDTH, paintedWidth)
}
0 голосов
/ 05 июня 2014

Очевидно, на пару лет позже, но я столкнулся с подобной проблемой (хотя я использую 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, оно превысит любую максимальную ширину, которая у вас есть.установлен.

0 голосов
/ 15 июня 2011

Я не использовал состояние, но я использую идею фиктивного текста, чтобы иметь ширину. спасибо

мой код:

                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
                  }

            }
...