Home > Enterprise >  Qt FontMetrics boundingrect vs Geometry rect
Qt FontMetrics boundingrect vs Geometry rect

Time:10-19

QString sText1 = "Sample Text890\nSample Text 890";
QString sText2 = "Sample Text890 Sample Text 890";
label1_->setText(sText1);
label2_->setText(sText2);
label1_->setWordWrap(false);
label2_->setWordWrap(false);
label1_->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
label2_->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);

Numbered boxes show metrics/information of corresponding labels just above them.

case 1: BoundingRect width is NOT equal to label widthx2 BoundingRectHeight is equal to label widthx2

case 2: BoundingRect width and height matches with label's width and height

BoundingRect WITHOUT TextWrap

case 3: No clue how boundingrect and label geometry are related!!

case 4: No clue how boundingrect and label geometry are related!!

BoundingRect WITH TextWrap

case 5:

QString sText1 = "Sample Text890\nSample Text 890";
QString sText2 = "Sample Text890 Sample Text 890";
label1_->setWordWrap(true);
label2_->setWordWrap(true);

enter image description here Question: I'm confused how font's bounding rect and label's geometry are related.

EDIT: I have updated case 5 and case 6 with label word wrap TRUE.

CodePudding user response:

From the That's odd...

Relations with the QLabel size

By default, QLabel does not wrap text (see the wordWrap property), so case 3 and 4 are not related because you explicitly specified that option for the font metrics. That said, you can get consistent result if you understand how text layout works.

For instance, to get a consistent bounding rect, use a very big rectangle as source:

QRect rect1 = fontMetrics.boundingRect(QRect(0, 0, 2000, 2000), Qt::TextWordWrap, sText1);

Which will return a size equal to the label basic sizeHint(). Obviously, since the source rectangle is that big, the word wrap option is useless, and you'll get the same result using 0 instead of Qt::TextWordWrap.

On the other hand, you can have the same result of the bounding rect that you got with the empty QRect, using the minimumSizeHint() and with wrapping enabled:

label.setWordWrap(true)
QSize minWidth = label.minimumSizeHint().width()
QRect boundingRect(0, 0, minWidth, label.heightForWidth(minWidth))

Remember, though, that using word wrapping in QLabel can have counter intuitive and unwanted results; while those results might seem unexpected, they actually are expected (see the note about layout issues: Qt layout management is not the same as a webpage, and the priority is always for all widgets, even if it's for the sake of a label. If the label must support wrapping but it's also placed in a complex layout, you need to explicitly set a reasonable minimum size (width, height, or both) whenever the layout also contains widgets that can adapt their size based on the overall available size; see the related note below.

Final considerations

  • QLabel uses parts of the Qt rich text processing framework, specifically QTextDocument, its document layout and the basic QTextLayout; unfortunately, probably due to performance reasons, all those components are private for QLabel; the only way to reliably compute a QLabel size (in the rare case for which this should be really needed) is to have deep knowledge of the above aspects;
  • QFontMetrics and QTextLayout are closely related: the former uses the latter to compute the size of laid out text (boundingRect(QRect, flags, text)), and vice versa for computing basic glyph sizes;
  • Qt layout managers will try their best to fit a word-wrapped label in the layout, but, as explained above, results may vary;
  • word-wrapped text should not be part of a layout: while this might be considered a Qt limitation, it's almost always a bad choice from the UX perspective (remember, a program is not a webpage, which is scrollable by nature); those texts should probably be put in a scroll area, so eventually consider using a QTextEdit or QPlainTextEdit set as readOnly and eventually a transparent background to make it look "like a label";
  • any padding/border/margin set with setContentsMargins() or QSS (Qt style sheets) must be added manually when trying to use font metrics;
  • Related