QFont 理论总结
一、概述
QFont类指定用于绘制文本的时候来描述字体的工具类。QFont可以看作是对系统上一个或多个字体的查询。
当我们创建QFont对象时,我们可以指定希望字体具有的各种属性。Qt将使用具有指定属性的字体,或者如果没有匹配的字体存在,Qt将使用最接近匹配的已安装字体。实际使用的字体属性可以从QFontInfo对象中检索。如果窗口系统提供精确匹配,则 exactMatch() 返回 true。使用 QFontMetricsF 来获得测量值,例如,使用 QFontMetrics::width() 来获得字符串的像素长度。
没有特别设置的属性不会影响字体选择算法,而会首选默认值。
要加载特定的物理字体(通常由单个文件表示),请使用QRawFont。
注意,在使用QFont之前,必须存在QGuiApplication实例。你可以使用QGuiApplication::setFont()设置应用程序的默认字体。
二、使用
如果选定的字体不包括需要显示的所有字符,QFont将尝试在最接近的等效字体中查找字符。当QPainter从一个字体中绘制一个字符时,QFont将报告它是否具有该字符;如果没有,QPainter将绘制一个未填充的正方形。
像这样创建QFonts:
cpp
QFont serifFont("Times", 10, QFont::Bold);
QFont sansFont("Helvetica [Cronyx]", 12);
在构造函数中设置的属性也可以稍后设置,例如 setFamily(), setPointSize(), setPointSizeF(), setWeight()和setItalic()。其余的属性必须在构造后设置,例如setBold(), setUnderline(), setOverline(), setStrikeOut()和setFixedPitch()。
QFontInfo对象应该在设置字体属性之后创建。即使我们更改了字体的属性,QFontInfo对象也不会更改。
相应的"get"函数,例如 family(), pointSize() 等,返回设置的值,即使使用的值可能不同。实际值可以从QFontInfo对象中获得。
如果请求的字体族不可用,我们可以通过使用setStyleHint()选择特定的QFont::StyleHint和QFont::StyleStrategy来影响字体匹配算法。默认族(对应于当前样式提示)由defaultFamily()返回。
我们可以使用insertSubstitution()和insertSubstitutions()为字体族名称提供替换。可以使用removesubsutions()删除替换。使用substitute()来检索家族的第一个替代品,如果没有替代品,则检索家族名称本身。使用substitute()来检索一个家族的替代品列表(可以是空的)。
每个QFont都有一个key(),我们可以使用它作为缓存或字典中的键。如果希望存储用户的字体首选项,可以使用QSettings,用toString()写入字体信息,然后用fromString()读取。operator<<()和operator>>()函数也可用,但它们在数据流上工作。
可以使用setPixelSize()将屏幕上显示的字符的高度设置为指定的像素数;然而,使用setPointSize()具有类似的效果,并提供设备独立性。
加载字体可能会很消耗资源,尤其是在X11上。QFont包含广泛的优化,使QFont对象的复制快速,并缓存它所依赖的缓慢的窗口系统函数的结果。
三、字体匹配算法
字体匹配算法工作原理如下:
- 搜索指定的字体族(由setFamilies()设置)。
- 如果没有找到,那么如果指定的字体族存在并且可以用来表示正在使用的书写系统,它将被选中。
- 如果不支持,则选择支持书写系统的替代字体。字体匹配算法将尝试为QFont中设置的所有属性找到最佳匹配。如何做到这一点因平台而异。
- 如果系统中不存在支持该文本的字体,那么将在其位置显示特殊的"缺失字符"框。
注意:如果选择的字体,虽然支持一般的书写系统,但缺少一个或多个特定字符的字形,那么Qt将尝试为这个或这些特定字符找到一个备用字体。此功能可以使用QFont:: nofontmerge样式策略禁用。
在Windows中,对"Courier"字体的请求会自动更改为"Courier New",这是Courier的改进版本,允许平滑缩放。旧的"Courier"位图字体可以通过设置PreferBitmap样式策略来选择(参见setStyleStrategy())。
一旦找到一个字体,剩下的属性将按照优先级的顺序进行匹配:
- fixedPitch()
- pointSize() (see below)
- weight()
- style()
如果你有一个匹配family的字体,即使其他属性都不匹配,这个字体也会优先选择一个不匹配family但匹配其他属性的字体。这是因为字体系列是主要的搜索条件。
如果点大小在请求点大小的20%以内,则定义为匹配。当几个字体匹配并且仅通过点大小区分时,将选择与请求的点大小最接近的字体。
用于绘制文本的实际字体、字体大小、粗细和其他字体属性将取决于窗口系统下所选字体的可用性。QFontInfo对象可用于确定用于绘制文本的实际值。
例子:
cpp
QFont f("Helvetica");
如果你同时拥有Adobe和Cronyx Helvetica字体,你可能会得到任何一个。
cpp
QFont f("Helvetica [Cronyx]");
我们可以在字体名称中指定我们想要的。上面例子中的字体 f 将被设置为"Helvetica [Cronyx]"。
要确定窗口系统中实际使用的字体的属性,可以使用QFontInfo对象,例如:
cpp
QFontInfo info(f1);
QString family = info.family();
要查找字体度量,请使用QFontMetrics对象,例如:
cpp
QFontMetrics fm(f1);
int textWidthInPixels = fm.horizontalAdvance("How many pixels wide is this text?");
int textHeightInPixels = fm.height();