我想将文本放入气泡内,并且我希望气泡等于文本宽度,但如果文本长度太长,我希望文本自动换行并等于父宽度。
此代码有效,但如果文本太长,文本不会换行:
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"
}
}
你可以几乎通过状态巧妙地做到这一点。问题在于,尝试通过将父级的宽度分配给文本框的 PaintWidth 来设置父级的宽度意味着它随后会设置文本框的宽度,而 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
}
}
]
}
这是另一种方法,使用 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
}
}
}
聚会已经很晚了,但干净的解决方案是使用嵌入式 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
}
}
您也可以使用上面提到的虚拟文本框尝试类似的操作:
width: Math.min(dummy_text.paintedWidth, 250)
这将使用文本的绘制尺寸,除非它大于您指定的像素宽度。
试试这个:
Text {
property int MAX_WIDTH: 400
width: MAX_WIDTH
onTextChanged: width = Math.min(MAX_WIDTH, paintedWidth)
}
我没有使用状态,但我使用虚拟文本的想法来具有宽度。谢谢
我的代码:
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
}
}
显然晚了几年,但我刚刚遇到了类似的问题(虽然我使用的是 elide 而不是wrapper,但基础知识是相同的)。 我最终得到了一个看起来简单干净的解决方案,所以我想如果其他人遇到这个问题它可能会有所帮助。 以原代码为例:
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。
对于那些多年后发现这个问题的人来说,这是一个现代的解决方案。
只要有最大宽度,您就想利用
Layout.maximumWidth
,这需要使用布局。由于我们只有一个组件,因此无论使用 RowLayout、ColumnLayout 还是 GridLayout 都没有关系。
import QtQuick
import QtQuick.Layouts
RowLayout {
Rectangle {
implicitWidth: messageBox.implicitWidth + 5
implicitHeight: messageBox.implicitHeight + 5
Layout.maximumWidth: messageBox.maxWidth + 5
Layout.fillWidth: true
color: modelData.myMessage ? "#aa84b2":"#380c47"
radius: 10
Text {
property alias maxWidth: dummy.implicitWidth
id:messageBox
anchors.fill: parent
anchors.margins: 2.5
text: '<b><font color=purple>'+modelData.message+'</font></b> '
wrapMode: Text.WordWrap
Text {
id: dummy
text: parent.text
visible: false
}
}
}
}
这个例子最好从里到外进行评估。
Text {
anchors.fill: parent
anchors.margins: 2.5
clip: true
}
文本组件使用
anchors.fill
和 anchors.margins
将自身限制在其父级(矩形)的边界内。它现在知道它需要有多大以及应该在哪里。
然而,现在矩形的宽度和高度都是0,这可以通过为文本设置
clip: true
来看到:
矩形是布局的直接子级,这意味着它的大小和位置由布局管理(与文本不同,文本管理自己的大小和位置)。虽然布局知道矩形应该在哪里(Layout.alignment
有默认值),但它不知道它应该有多大。它的大小默认为零。
Rectangle {
implicitWidth: messageBox.implicitWidth + 5
implicitHeight: messageBox.implicitHeight + 5
Text {
id:messageBox
anchors.fill: parent
anchors.margins: 2.5
}
}
我们可以使用
implicitWidth
和
implicitHeight
来通知布局,它们共同构成了矩形的首选尺寸。如果我们无法访问
implicitWidth
和 implicitHeight
,我们将使用 Layout.preferredWidth
和 Layout.preferredHeight
。
RowLayout {
Rectangle {
implicitWidth: messageBox.implicitWidth + 5
implicitHeight: messageBox.implicitHeight + 5
Layout.maximumWidth: messageBox.maxWidth + 5
Text {
property alias maxWidth: dummy.implicitWidth
id:messageBox
anchors.fill: parent
anchors.margins: 2.5
Text {
id: dummy
text: parent.text
visible: false
}
}
}
}
Layout.maximumWidth
可用于限制布局内组件的宽度。矩形的宽度应限制为文本未换行时的宽度。要确定此宽度,可以使用带有
wrapMode: Text.NoWrap
的相同文本进行测量。由于它只是用于测量,所以使用visible: false
来防止它被看见并影响布局。Layout.maximumWidth
仅适用于
Layout.fillWidth: true
。在这种情况下,
Layout.fillWidth: true
的行为类似于
anchors{left: parent.left;right:parent.right}
,只不过它尊重 Layout.maximumWidth
。RowLayout {
Rectangle {
implicitWidth: messageBox.implicitWidth + 5
implicitHeight: messageBox.implicitHeight + 5
Layout.maximumWidth: messageBox.maxWidth + 5
Layout.fillWidth: true
Text {
property alias maxWidth: dummy.implicitWidth
id:messageBox
anchors.fill: parent
anchors.margins: 2.5
Text {
id: dummy
text: parent.text
visible: false
}
}
}
}