QPlainTextEdit with equal line heights
-
I need to get equal line-heights in a editor class. It contains only the visible part of very huge files. I use
QPlainTextEdit
as base because I only need some syntax highlighting. The project must work on windows, linux, and macOS.I need to estimate how many lines will fit into the editors visible part before painting to avoid flickering. Therefore it should not depend on dynamic line heights.
Several problems occurred:
- For some fonts
QFontMetrics::lineSpacing()
may result in different heights depending on some attributes (e.g. italic forCourier New
is 17 - regular is 16). - Sometimes
QFontMetrics::lineSpacing()
returns a way lower value (-4) than the resultingQTextLayout::boundingRect()
uses in the end (especially on mac). - trying to force a fixed line height based on the current font using
QTextBlockFormat::setLineHeight(30, QTextBlockFormat::FixedHeight)
was ignored byQPlainTextEdit
. - Modifying
QTextLayout::position()
in eachQTextBlock
has a visual effect but produces graphical errors on interacting with the text (e.g. mouse drag).
Any ideas how to force all lines into a given height?
Regards,
Jazzco - For some fonts
-
I'm getting closer to a solution. One way to get the same height for all lines is to use
QFont::setHintingPreference(QFont::PreferNoHinting);
What I have not yet solved satisfactorily is the determination of the height. In most cases it is possible to get the correct height with
qtextline.height() + (qtextline.leading() < 0 ? qCeil(qtextline.leading()) : 0);
Unfortunately the
QTextLine
represents the current old representation - not the upcoming new one, for which this calculation is the requirement. The central problem is that I did not manage to find this value in any of the members of the font or its metrics. I digged inside the Qt sources to understand how the height of the QTextLine is calculated but ended up in several internal undocumented engines.An example:
TheQFontMetrics
on Windows 10 forCourier New
in point size 8 has aheight
and alineSpacing
of 12. For whatever reasons theQTextLine
created with this font inQPlainTextEdit
returns a height of 13. Where does this extra pixel come from?Regards
Jazzco -
Ok, I finally found the solution. The issue was the use of
QPlaintTextEdit::fontMetrics()
method. It provides only the integer dataQFontMetrics
of the font and rounds values below .5 to the floor. To solve this an instance ofQFontMetricsF
is needed. Additionally for some fonts the lineSpacing is smaller than calculating the bounding QRectF of the string"Äg"
. So my solution is:int TextViewEdit::lineCount() { QFontMetricsF metric(font()); qreal lineHeight = qCeil(qMax(metric.lineSpacing(), metric.boundingRect("Äg").height())); return qFloor(qreal(viewport()->height()) / lineHeight); }