Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Empty space above and below Text elements in a ColumnLayout

Tags:

qt

qml

I have QML Text elements in a ColumnLayout like so:

import QtQuick 2.0
import QtQuick.Layouts 1.1
Item {
    Rectangle {
        ColumnLayout {
            anchors.fill: parent
            anchors.bottomMargin: 5
            Canvas {
                Layout.fillHeight: true
                Layout.fillWidth: true
            }
            Text {}
            Text {}
            Text {}
        }
    }
}

The canvas fill the top part of the column nicely and the Texts line up beneath it just fine. That anchors.bottomMargin sets a small margin only at the very bottom. But no matter what margins or anchors I set for the Texts, there is a lot of vertical empty space between them. The text is just numbers so there is no concern about characters that need to take up more room. How do I get rid of this space?

like image 371
John Q. Workaday Avatar asked Sep 18 '25 18:09

John Q. Workaday


2 Answers

I've run into this issue as well, and there wasn't a solution. However, in Qt 5.4, the FontMetrics and TextMetrics QML types were added.

TextMetrics

FontMetrics has a comprehensive API which mirrors the C++ QFontMetricsF class, with some of it being imperative (functions). TextMetrics takes the functions in FontMetrics and makes them declarative (properties) for convenience, plus some extra properties for completeness.

Given some text string, TextMetrics will provide you with the tightBoundingRect property, which, as its name suggests, is a tight bounding rectangle around the string, without the extra space that you normally see. Take that height from the height of a string with only numbers in it, and you get the superfluous height than can be used as negative spacing:

import QtQuick 2.4

Item {
    Rectangle {
        anchors.fill: parent

        TextMetrics {
            id: metrics
            text: "1"
        }

        Column {
            anchors.fill: parent
            anchors.bottomMargin: 5
            spacing: -(metrics.height - metrics.tightBoundingRect.height)

            Text { text: "123" }
            Text { text: "123" }
            Text { text: "123" }
        }
    }
}

Note the warning from the documentation:

Warning: Calling this method is very slow on Windows.

That shouldn't be a problem if you only set the text/font on the TextMetrics object once though, as it will only calculate it once.

Line height

An alternative, but sketchy approach is to basically guess a value for the lineHeight property of each Text item.

import QtQuick 2.0

Item {
    Rectangle {
        anchors.fill: parent

        Column {
            anchors.fill: parent
            anchors.bottomMargin: 5
            Text { text: "123"; lineHeight: 0.8 }
            Text { text: "123"; lineHeight: 0.8 }
            Text { text: "123"; lineHeight: 0.8 }
        }
    }
}

Negative spacing

As Shubhanga said, negative spacing will also work, but it's also not so great:

import QtQuick 2.0

Item {
    Rectangle {
        anchors.fill: parent

        Column {
            anchors.fill: parent
            anchors.bottomMargin: 5
            spacing: -4
            Text { text: "123" }
            Text { text: "123" }
            Text { text: "123" }
        }
    }
}

Text height

Again, mentioned by Shubhanga, setting the text's height explicitly will work, but there's still guesswork involved. Like the two solutions above, you'll have to change the value you subtract from the height each time you change font size, and it won't scale between devices (low DPI desktop PC vs high DPI mobile):

import QtQuick 2.0

Item {
    readonly property int heightAdjustment: 5
    Rectangle {
        anchors.fill: parent

        Column {
            anchors.fill: parent
            anchors.bottomMargin: 5
            Text {
                text: "123";
                height: implicitHeight - heightAdjustment
            }
            Text {
                text: "123";
                height: implicitHeight - heightAdjustment
            }
            Text {
                text: "123";
                height: implicitHeight - heightAdjustment
            }
        }
    }
}
like image 119
Mitch Avatar answered Sep 22 '25 04:09

Mitch


Have you tried using spacing property? This is used to set spacing between layout's contents. The default value is 5. Try setting it as 0.

Reference ColumnLayout spacing property

like image 32
Programmer Avatar answered Sep 22 '25 06:09

Programmer