Chapter 20. Working with Fonts

Every developer has faced this: text in the interface “floats”, gets cut off, looks different on different platforms, or suddenly breaks careful layout. Font seems like a detail — until it starts ruining the impression of the entire application.

This chapter will discover that working with fonts isn’t about “choosing Times or Arial”. We’ll reveal how Qt actually calculates text sizes, why some strings fit perfectly in the interface while others don’t, and what hidden mechanism allows getting predictable results without manual adjustments. You’ll learn the secret that professional developers use to make interfaces look neat and stable on Windows, Linux, and macOS.

The chapter covers 3 key Qt classes for working with fonts, shows real text measurements in pixels, and practical techniques for alignment, wrapping, and text truncation — including intelligent mid-string breaking. Result: fewer workarounds and up to 3 times fewer manual UI fixes.

Skipping this chapter means one thing: you’ll keep guessing why text behaves “strangely” instead of precisely controlling it.

This chapter includes ready-to-use code examples.

Chapter Self-Check

Why is a scalable typeface called a “perfect mathematical description” and how does this affect font output?Answer
Correct answer: It allows displaying fonts without distortion at any size, and rasterization functions automatically convert mathematical representation to a raster matrix without additional developer effort.
Why specify multiple fonts separated by commas in QFont("XYZ Font, Arial, Helvetica, sans-serif")?Answer
Correct answer: This provides a fallback font system: if XYZ Font is unavailable, Qt will intelligently choose Arial, then Helvetica, then any sans-serif font, making behavior more predictable.
What’s the difference between width() and horizontalAdvance() methods of QFontMetrics class?Answer
Correct answer: The width() method can accept part of a string and number of characters to measure, while horizontalAdvance() measures the full size of the entire passed string with all its characters.
Why use the boundingRect() method before displaying text?Answer
Correct answer: It returns a QRect object with dimensions of the rectangular area needed to display text, allowing you to determine geometry in advance and properly plan text placement in the interface.
What do the values returned by ascent() and descent() methods mean and why are they important?Answer
Correct answer: ascent() returns maximum character height above baseline (including diacritics), and descent() — maximum value below baseline; they’re necessary for precise vertical text alignment.
Why can the TextDontClip flag be problematic when outputting long text?Answer
Correct answer: This flag ensures text won’t be clipped even when going beyond specified area boundaries, which can lead to text overlapping other interface elements.
How do you fill text with a gradient and why is the gradient passed through QPen object rather than QBrush?Answer
Correct answer: Create QLinearGradient with color transitions, then pass to QPen constructor which is set via setPen(). Pen is used because text in QPainter is drawn as an outline, not filled as a shape.
In what practical situations is the elidedText() method preferable to clipping or text wrapping?Answer
Correct answer: When displaying directory paths, long file names, or titles in limited space where it’s important to show the user that text is truncated while preserving the beginning and/or end of the string.
Why does the elidedText() method return a new string instead of modifying the original?Answer
Correct answer: This keeps the original text unchanged for possible subsequent use and follows data immutability principles; displayed representation is separated from stored data.
What’s the difference between setFont() for a widget and QApplication::setFont()?Answer
Correct answer: QWidget::setFont() sets font only for a specific widget, while static method QApplication::setFont() sets default font for the entire application.
Why does the mnemonic mechanism TextShowMnemonic work differently on different platforms?Answer
Correct answer: Qt correctly handles ampersands and assigns access keys, but underline visibility is determined by platform: in Windows 10/11 it’s hidden by default, in Linux depends on theme, and in macOS mnemonics aren’t used at all.
What will happen if you use TextWordWrap flag together with TextSingleLine?Answer
Correct answer: Flag conflict will occur: TextSingleLine ignores newline characters, while TextWordWrap tries to wrap text to a new line, leading to unpredictable results — only one of these flags should be used.
What might leftBearing() and rightBearing() methods of QFontMetrics class be used for?Answer
Correct answer: They return left and right letter spacing in pixels, which is important for precise character positioning, especially when creating custom text rendering or animating individual letters.

Practical Exercises

Easy Level

System Fonts Information
Create an application that displays a list of all installed system fonts in a QTextEdit widget. For each font, output its name using that font itself. Font size should be 14pt.
Hints: Use QFontDatabase class and families() method to get font list. For each font, create an HTML string with <font face=”…”> tag. Insert result into QTextEdit using setHtml().

Medium Level

Font Metrics Analyzer
Develop a widget that allows user to select font and its size (via combo boxes), enter text in a text field, and see visualization of this text’s metrics: baseline, ascent, descent, width, height. Use different colors to display various characteristics. Output numeric metric values.
Hints: Create custom widget with overridden paintEvent(). Use QFontMetrics to get all necessary metrics. Draw horizontal lines for baseline, ascent, and descent in different colors. Use QPainter::drawLine() and drawText() for visualization.

Hard Level

Adaptive Text Widget with Effects
Create a custom text display widget that automatically adapts to window size: with sufficient space shows full text with gradient fill, when reducing size applies elided text (with choice of break position), and at critically small size switches to multiline mode with word wrap. Add ability to select gradient style and break position via context menu.
Hints: Override paintEvent() and resizeEvent(). In paintEvent(), check current widget width and apply corresponding display strategy. For gradient, use QLinearGradient with dynamic coordinates depending on widget size. Use fontMetrics().horizontalAdvance() to determine width thresholds. Add contextMenuEvent() for settings menu.

💬 Join the Discussion!

Figured out font metrics and nuances of displaying text in Qt? Have questions about choosing between different drawText() methods or working with gradient fill?

Share your findings working with fonts, tell us about non-standard solutions, or help other readers understand QFontMetrics subtleties!

Leave a Reply

Your email address will not be published. Required fields are marked *