Перенос текста Qml (максимальная ширина)
Я хотел бы поместить текст внутри пузыря, и я хочу, чтобы мой пузырь был равен ширине текста, но если длина текста слишком длинная, я хотел бы, чтобы текст автоматически обертывался и был равен родительской ширине.
этот код работает, но текст не переносится, если текст слишком длинный:
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 ответов
вы можете почти сделайте это аккуратно с состояниями. Проблема в том, что попытка установить ширину родителя, назначив его paintedWidth текстового поля, означает, что он затем устанавливает ширину текстового поля, которую QML обнаруживает как влияющую на paintedWidth. Он не будет рекурсировать дальше, чем это, но 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
}
}
]
}
вот еще один способ, который использует компонент.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
}
}
}
вы также можете попробовать что-то вроде этого, используя фиктивное текстовое поле, упомянутое выше:
width: Math.min(dummy_text.paintedWidth, 250)
Это будет использовать окрашенный размер текста, если он не превышает заданную ширину пикселя.
Я не использовал состояние, но я использую идею фиктивного текста для ширины. спасибо
мой код :
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
}
}
попробуйте это:
Text {
property int MAX_WIDTH: 400
width: MAX_WIDTH
onTextChanged: width = Math.min(MAX_WIDTH, paintedWidth)
}
очевидно, пару лет спустя, но я просто столкнулся с подобной проблемой (хотя я использую 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, если слово слишком длинное, чтобы соответствовать всей ширине текстового элемента, оно превысит любую maxWidth вы установили.