I have to perform a very simple task: I want to display a piece of text inside a rectangle and the size of that rectangle should precisely be the width of the text.
In C++, it's fairly easy to do. Just define the QString and apply the QFontMetrics to get its width. Then define the rectangle graphics element to have that size. It's done within five minutes.
I have heard that QML is easier to use. Therefore, I was expecting to solve that problem in less than five minutes. I didn't, and I'm still stuck at it. Here's what I have tried:
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")
}
}
This doesn't work for some reason I don't understand. I have found a way to do it in a way that doesn't exactly suits my needs:
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")
}
}
In this case, when I click the rectangle, it gets the correct width. Nevertheless, I am not interested in this solution, because I don't want to have to click to get a rectangle with the correct size.
I want that the rectangle's size gets the correct size whenever myText
changes text. The use of onTextChanged
in the Text item doesn't work either.
What am I missing here?
As far as I know, Font metrics were made available to developers in Qt 5.4, so they are relatively new, in QML. You got mainly FontMetrics
and TextMetrics
. A simple usage example:
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
}
}
}
As noted by Phrogz
in the comment below, the TextMetrics
type does not support measuring wrapped text.
For what is worth I've never ever had the need to use metrics in QML. For me content*
or painted*
properties served the purpose and, as of Qt 5.12, they seem to work fine. Aka the following two solutions generate the correct visual behaviour:
// 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")
}
}
I would prefer those solutions to the usage of metrics for such a simple use case as the one proposed by the OP. For the opposite case - fitting a text in a specific size - a combination of properties can do the trick, e.g.:
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
}
}
Here the pixel size is simply over the top but the text still fits because a minimum size of 2
is set and the text has a clear fitting policy and clear boundaries, defined by the anchoring.
I'm sure Label component will do the job:
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
}
}
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With