Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Advanced Text Rendering and Layout Techniques in QML

Tech May 10 3

This guide demonstrates practical implementations for dynamic text presentation, typographic control, and automated layout distribution within the QML ecosystem. Each segment focuses on a specific rendering mechanism, providing optimized code structures for production environments.

Animated Character Spacing and Opacity Fades

Creating synchronized transition effects often requires managing multiple property animations simultaneously. The following implementation pairs letter-spacing expansion with an opacity fade, using independent sequential chains that share an identical cycle duration. Upon completion, a script action randomizes the element's position for continuous looping.

import QtQuick 2.0

Rectangle {
    id: mainCanvas
    width: 320; height: 480
    color: "#000000"

    Item {
        id: positionHolder
        x: mainCanvas.width / 2
        y: mainCanvas.height / 2

        Text {
            id: displayLabel
            anchors.centerIn: parent
            color: "#FFFFFF"
            text: "Hello world!"
            font.pixelSize: 32

            SequentialAnimation on font.letterSpacing {
                loops: Animation.Infinite
                NumberAnimation {
                    from: 0; to: 50
                    easing.type: Easing.InQuad
                    duration: 3000
                }
                ScriptAction {
                    script: {
                        positionHolder.y = (mainCanvas.height / 4) + (Math.random() * mainCanvas.height / 2);
                        positionHolder.x = (mainCanvas.width / 4) + (Math.random() * mainCanvas.width / 2);
                    }
                }
            }

            SequentialAnimation on opacity {
                loops: Animation.Infinite
                NumberAnimation { from: 1; to: 0; duration: 2600 }
                PauseAnimation { duration: 400 }
            }
        }
    }
}

Dynamic Font Loading and Typography Controls

QML provides the FontLoader component to asynchronously load system, local, or remote typefaces. Once resolved, the loaded family name can be bound to font.family. Combined with built-in properties like capitalization, weight, and italic, developers can achieve complex stylistic variations without external assets.

import QtQuick 2.0

Rectangle {
    property string sampleContent: "The quick brown fox jumps over the lazy dog."
    width: 320; height: 480
    color: "#4682B4"

    FontLoader { id: monospaceSource; name: "Courier New" }
    FontLoader { id: assetFont; source: "content/fonts/custom.otf" }
    FontLoader { id: remoteFont; source: "https://cdn.example.com/fonts/webfont.ttf" }

    Column {
        anchors.fill: parent
        anchors.margins: 10
        spacing: 15

        Text {
            text: sampleContent
            color: "#B0C4DE"
            width: parent.width
            wrapMode: Text.WordWrap
            font.family: "Georgia"
            font.pixelSize: 20
        }
        Text {
            text: sampleContent
            color: "#B0C4DE"
            width: parent.width
            wrapMode: Text.WordWrap
            horizontalAlignment: Text.AlignHCenter
            font.family: "Georgia"; font.pixelSize: 20
            font.capitalization: Font.AllUppercase
        }
        Text {
            text: sampleContent
            color: "#B0C4DE"
            width: parent.width
            wrapMode: Text.WordWrap
            horizontalAlignment: Text.AlignRight
            font.family: monospaceSource.name
            font.pixelSize: 20
            font.weight: Font.Bold
            font.capitalization: Font.Lowercase
        }
        Text {
            text: sampleContent
            color: "#B0C4DE"
            width: parent.width
            wrapMode: Text.WordWrap
            font.family: monospaceSource.name
            font.pixelSize: 20
            italic: true
            font.capitalization: Font.SmallCaps
        }
        Text {
            text: sampleContent
            color: "#B0C4DE"
            width: parent.width
            wrapMode: Text.WordWrap
            font.family: assetFont.name
            font.pixelSize: 20
            font.capitalization: Font.Capitalize
        }
        Text {
            text: {
                if (remoteFont.status === FontLoader.Ready) return sampleContent
                if (remoteFont.status === FontLoader.Loading) return "Fetching resource..."
                return "Font unavailable"
            }
            color: "#B0C4DE"
            width: parent.width
            wrapMode: Text.WordWrap
            font.family: remoteFont.name
            font.pixelSize: 20
        }
    }
}

Enumerating Installed System Typefaces

The QML engine exposes a runtime list of installed fonts through Qt.fontFamilies(). Binding this data source to a ListView enables immediate visualization of available typography, with the modelData role serving both as the displayed name and the applied font family.

import QtQuick 2.0

Rectangle {
    width: 320; height: 480
    color: "#4682B4"

    ListView {
        anchors.fill: parent
        model: Qt.fontFamilies()

        delegate: Item {
            height: 40
            width: ListView.view.width

            Text {
                anchors.centerIn: parent
                text: modelData
                font.family: modelData
                font.pixelSize: 20
                color: "#FFFFFF"
            }
        }
    }
}

Inline HTML-like Styling and Embedded Media

QML supports a subset of CSS3 and HTML markup within Text components. Tags such as <b> and <i> handle emphasis, while <img> allows direct embedding of raster assets. Inline attributes control alignment, scaling, and vertical positioning relative to the baseline.

import QtQuick 2.0

Rectangle {
    id: uiContainer
    width: 320; height: 480
    focus: true
    color: "#DEDEDE"

    property int hAlignMode: Text.AlignLeft

    Flickable {
        anchors.fill: parent
        contentWidth: parent.width
        contentHeight: contentStack.height + 20

        Column {
            id: contentStack
            x: 10; y: 10
            spacing: 20
            width: parent.width - 20

            RichTextBlock {
                text: "This is a <b>joyful</b> face<img src="\"assets/smile.png\""></img>"
            }
            RichTextBlock {
                text: "A vertically <b>centered<img align="\"middle\"/" src="\"assets/big-smile.png\""></img>expression</b>."
            }
            RichTextBlock {
                text: "Compact icon overlay<img height="\"16\"" src="\"assets/smile.png\"" width="\"16\""></img>integrated seamlessly."
            }
            RichTextBlock {
                text: "Top-aligned<img align="\"top\"" height="\"50\"" src="\"assets/starfish.png\"" width="\"50\""></img>with corresponding bottom-aligned<img height="\"50\"" src="\"assets/heart.png\"" width="\"50\""></img>markers."
            }
            RichTextBlock {
                text: "Multi-size branding<img align="\"middle\"" height="\"60\"" src="\"assets/logo-main.png\"" width="\"55\""></img><img align="\"middle\"" height="\"40\"" src="\"assets/logo-alt.png\"" width="\"37\""></img><img align="\"middle\"" height="\"20\"" src="\"assets/logo-mini.png\"" width="\"18\""></img>stacked horizontally."
            }
            RichTextBlock {
                text: "Variable scale heart icons<img align="\"bottom\"" height="\"20\"" src="\"assets/heart.png\"" width="\"20\""></img><img align="\"bottom\"" height="\"30\"" src="\"assets/heart.png\"" width="\"30\""></img><img height="\"40\"" src="\"assets/heart.png\"" width="\"40\""></img><img align="\"bottom\"" height="\"50\"" src="\"assets/heart.png\"" width="\"50\""></img>rendered dynamically."
            }
            RichTextBlock {
                text: "Externally hosted asset<img align="\"middle\"" height="\"48\"" src="\"https://external.cdn.net/image.png\"" width="\"48\""></img>loaded at runtime."
            }
            RichTextBlock {
                verticalAlignment: Text.AlignVCenter
                text: "Explicit height constraint ensuring stable baseline alignment for <b>mixed media</b> content."
            }
        }
    }

    Keys.onUpPressed: uiContainer.hAlignMode = Text.AlignHCenter
    Keys.onLeftPressed: uiContainer.hAlignMode = Text.AlignLeft
    Keys.onRightPressed: uiContainer.hAlignMode = Text.AlignRight
}

Flow-Based Multi-Column Line Distribution

For responsive documentation or lengthy content blocks, automatic column wrapping prevents manual overflow handling. By listening too the onLineLaidOut signal, developers can intercept individual line metrics. When a line exceeds the vertical boundary, its coordinates are redirected to a secondary column region, effectively creating a newspaper-style flow.

import QtQuick 2.0

Rectangle {
    id: scrollArea
    width: 320; height: 480
    focus: true

    property real columnGap: 8

    Text {
        id: flowLabel
        anchors.fill: parent
        anchors.margins: 10
        wrapMode: Text.WordWrap
        font.family: "Times New Roman"
        font.pixelSize: 14
        textFormat: Text.StyledText
        horizontalAlignment: Text.AlignJustify

        text: "<a href="\"http://example.com\"">Documentation Link</a>. <br></br>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer at ante dui.<ul type="\"bullet\""><li>Coffee<br></br><ol type="\"a\""><li>Espresso</li><li>Cappuccino</li></ol></li></ul><font color="\"#333333\""><i>Advanced typography <b>engine</b> demonstration featuring dynamic redistribution.</i></font>"

        onLineLaidOut: {
            line.width = width / 2 - columnGap

            if (line.y + line.height >= height) {
                line.y -= height - columnGap
                line.x = width / 2 + columnGap
            }
        }
    }
}

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.