如何在 QML 中将一些文本包裹在一个矩形中?

How to wrap some text in a rectangle in QML?

我必须执行一个非常简单的任务:我想在一个矩形内显​​示一段文本,并且该矩形的大小应该恰好是文本的宽度。

在 C++ 中,这很容易做到。只需定义 QString 并应用 QFontMetrics 来获取其宽度。然后定义具有该尺寸的矩形图形元素。它在五分钟内完成。

听说QML比较好用。因此,我期望在不到五分钟的时间内解决该问题。我没有,我仍然坚持下去。这是我尝试过的:

Rectangle {
    width: myText.contentWidth
    height: myText.contentHeight

    Text {
        anchors.fill:parent
        id: myText
        font.family: "Helvetica"
        font.pointSize: 50
        text:  qsTr("The string I want to display")
    }
}

由于我不明白的某些原因,这不起作用。我找到了一种不完全适合我需要的方法:

Rectangle {
    width: 100
    height: 100

    MouseArea {
       id: myMouseArea
       anchors.fill: parent
       onClicked: parent.width=myText.contentWidth 
       hoverEnabled: true
     }

    Text {
        anchors.fill:parent
        id: myText
        font.family: "Helvetica"
        font.pointSize: 50
        text:  qsTr("The string I want to display")
    }
}

在这种情况下,当我单击矩形时,它会获得正确的宽度。不过,我对这个解决方案不感兴趣,因为我不想通过单击来获得正确大小的矩形。

我希望每当 myText 更改文本时矩形的大小都得到正确的大小。在文本项中使用 onTextChanged 也不起作用。

我在这里错过了什么?

据我所知,在 Qt 5.4 中开发人员可以使用字体指标,因此在 QML 中它们相对较新。你得到的主要是 FontMetrics and TextMetrics。一个简单的用法示例:

import QtQuick 2.4
import QtQuick.Window 2.2

Window {
    visible: true
    width: 280; height: 150

    TextMetrics {
        id: textMetrics
        font.family: "Arial"
        font.pixelSize: 50
        text: "Hello World"
    }

    Rectangle {
        width: textMetrics.width
        height: textMetrics.height
        color: "steelblue"

        Text {
            text: textMetrics.text
            font: textMetrics.font
        }
    }
}

正如 Phrogz 在下面的评论中指出的那样,TextMetrics 类型 支持测量换行文本。


编辑

对于有价值的东西,我从来没有需要在 QML 中使用指标。对我来说 content*painted* 属性达到了目的,并且从 Qt 5.12 开始,它们似乎工作正常。又名以下两个解决方案生成正确的视觉行为:

// solution 1
Rectangle {
    width: myText.contentWidth
    height: myText.contentHeight

    Text {
        anchors.fill:parent
        id: myText
        font.family: "Helvetica"
        font.pointSize: 50
        text:  qsTr("The string I want to display")
    }
}

// solution 2
Rectangle {
    width: myText.paintedWidth
    height: myText.paintedHeight

    Text {
        anchors.fill:parent
        id: myText
        font.family: "Helvetica"
        font.pointSize: 50
        text:  qsTr("The string I want to display")
    }
}

对于像 OP 提出的这样一个简单的用例,我更喜欢这些解决方案而不是指标的使用。对于相反的情况 - 以特定大小调整文本 - 属性的组合可以达到目的,例如:

Rectangle {
    anchors.centerIn: parent
    width: 200
    height: 30

    Text {
        anchors.fill: parent
        text: "Wonderful Text"
        minimumPixelSize: 2
        fontSizeMode: Text.Fit
        font.pixelSize: 200
        horizontalAlignment: Text.AlignHCenter
        verticalAlignment: Text.AlignVCenter
    }
}

这里的像素大小只是超过了顶部,但文本仍然适合,因为设置了 2 的最小尺寸,并且文本具有明确的适合策略和清晰的边界,由锚定定义。

我确定 Label 组件可以完成这项工作:

import QtQuick 2.1
import QtQuick.Controls 2.4

ApplicationWindow {
    visible: true

    Column {
        Repeater {
            model: [
                {"color": "red", "radius": 1},
                {"color": "green", "radius": 2},
                {"color": "blue", "radius": 3}
            ]
            Label {
                padding: 0
                text: modelData.color
                font.family: "Helvetica"
                font.pointSize: 50
                background: Rectangle {
                   color: modelData.color
                   radius: modelData.radius
                }
            }
        }
    }
}

您不需要对文本项使用 anchors.fill: parent,因为文本父项的大小取决于文本本身的大小。这是导致绑定循环。

这一定没问题。

Rectangle  {
    width: myText.contentWidth
    height: myText.contentHeight

    Text {
        id: myText
        font.family: "Helvetica"
        font.pointSize: 50
        text:  qsTr("The string I want to display")
    }
}