QML Text Wrap (ancho máximo)
Pregunta
Me gustaría poner texto dentro de una burbuja, y quiero que mi burbuja sea igual al ancho del texto, pero si la longitud del texto es demasiado larga, me gustaría que el texto se envuelva automáticamente y sea igual al ancho principal.
Este código funciona pero el texto no está envolviendo si el texto es demasiado largo:
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"
}
}
e intenté esto, envoltura de texto, pero si el texto es demasiado pequeño, el ancho de la burbuja no es igual al tamaño del texto:
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"
}
}
Solución
Puedes casi Haz esto cuidadosamente con los estados. El problema es que intentar establecer el ancho del padre asignándolo al ancho pintado del cuadro de texto significa que luego establece el ancho del cuadro de texto, que QML detecta como un ancho pintado influyendo. No se recurriría más allá de esto, pero QML todavía patea advertencias. Una forma de evitar el problema es hacer lo siguiente, y tener un cuadro de texto invisible ficticio que simplemente funcione cuán ancho es/debería ser el texto. Es un poco hack, pero funciona bien.
Puede cambiar la propiedad "When" del estado para depender del tamaño del cuadro de texto ficticio (en lugar de la longitud de la cadena) si prefería un límite de píxel en el ancho de la caja.
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
}
}
]
}
Otros consejos
Aquí hay otra forma, que utiliza el script componente.onCompleted. Es más estático que mi otro método, por lo que supongo que depende de lo que quieras hacer con él.
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
}
}
}
También puede probar algo como esto, usando el cuadro de texto ficticio mencionado anteriormente:
width: Math.min(dummy_text.paintedWidth, 250)
Esto utilizará el tamaño pintado del texto a menos que sea mayor que su ancho de píxel especificado.
Prueba esto:
Text {
property int MAX_WIDTH: 400
width: MAX_WIDTH
onTextChanged: width = Math.min(MAX_WIDTH, paintedWidth)
}
No usé el estado, pero uso la idea de texto ficticio para tener ancho. Gracias
mi código :
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
}
}
Obviamente, un par de años tarde, pero me encontré con un problema similar (aunque estoy usando Elide en lugar de envoltura, pero los conceptos básicos son los mismos). Terminé con lo que parece una solución simple y limpia, así que pensé que si alguien más se encuentra con este problema, tal vez pueda ayudar. Usando el código original como ejemplo:
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"
}
}
El único problema para este ejemplo es que con Wordwrap, si una palabra es demasiado larga para adaptarse a todo el ancho del elemento de texto, excederá cualquier maxwidth que haya establecido.