跳转到主要内容

文本和字体

文本和字体是新式图形用户界面的一个十分重要的方面。 必须能够以应用支持的所有语言显示高质量抗锯齿文本。

TouchGFX支持通过TouchGFX Designer的文本视图创建和修改文本和字体排印。 TouchGFX Designer将文本和字体排印配置输出到电子表格(位于assets/texts/texts.xlsx)。 将此电子表格与字体文件一起输入字体和文本转换器工具,输出生成的TouchGFX可渲染的C++代码文件。

本文介绍文本和字体转换器工具,并说明如何通过代码和TouchGFX Designer使用在应用中生成的文本。

文本和字体排印

TouchGFX应用中的文本、翻译文件和字体排印存储在assets/texts/texts.xlsx电子表格中。 该电子表格包含两个工作表。 一个工作表定义应用中使用的字体排印,另一个工作表定义文本及其所有翻译文件。 此电子表格通常被称为“文本数据库”。

可以在TouchGFX Designer的文本视图中编辑字体排印,该视图支持文本和翻译文件的实时编辑和处理。 但是,也可以在texts.xlsx电子表格中直接编辑字体排印和文本。 通常不建议这样做,至少在开发阶段不建议。 如果对翻译使用外部资源,可以更容易地分享电子表格,而不是必须在TouchGFX Designer中进行。 如果在开发过程中编辑电子表格,由于TouchGFX Designer打开时会锁定texts.xlsx文件,因此必须关闭它才能进行编辑。

Further reading
如需获取关于如何创建和编辑字体排印、文本、翻译文件和语言的更多信息,请转至文本视图
Note
对于字形位图分布格式字体(.bdf),并不能渲染字体的所有字号。 如果字体排印纸中的给定字号与给定字体不匹配,字体转换实用工具将报告支持的字号。 将字体排印纸中的字号更新为支持的字号之一,即可解决问题。

文本转换器

文本转换器是将文本数据库中的文本信息转换为TouchGFX应用使用的内部C++格式的工具。 该工具是构建工具链不可或缺的一部分,将在构建模拟器时自动执行。 如果自上一次构建后文本数据库没有更新,则不执行文本转换器。

Note
文本转换器的输出目录为 generated/texts/。.

文本转换器将文本数据库中的所有指定文本转换为TouchGFX使用的文本格式。 格式被封装成名为TypedText的对象。 TouchGFX中的TypedText是文本内容本身与文本字体排印的组合实体。 字体排印包含文本的字体和字号,以及字体字形抗锯齿时使用的每像素位数(bpp)。

文本转换器生成名为generated/texts/include/texts/TextKeysAndLanguages.hpp的文件。 此文件包含引用文本数据库中所有文本的枚举TEXTS

请注意,枚举中的所有条目均生成自文本数据库每一行中规定的文本ID,但具有前置的T_并转换成大写字母。 应用中使用这些枚举值初始化TypedText。

TextKeysAndLanguages.hpp还包含枚举LANGUAGES,它指定文本数据库中现有的所有语言。 命名与文本数据库中的语言列相同。

generated/texts/include/texts/TextKeysAndLanguages.hpp
/* DO NOT EDIT THIS FILE */
/* This file is autogenerated by the text-database code generator */

#ifndef TEXT_KEYS_AND_LANGUAGES_HPP
#define TEXT_KEYS_AND_LANGUAGES_HPP


typedef enum {
GB,
DE,
NUMBER_OF_LANGUAGES
} LANGUAGES;


typedef enum {
T_TEMPERATURE_READOUT,
T_TEMPERATURE_HEADLINE,
NUMBER_OF_TEXT_KEYS
} TEXTS;

#endif /* TEXT_KEYS_AND_LANGUAGES_HPP */

文本转换器

文本转换器是将字体文件中的信息与文本数据库中的信息进行组合并生成应用需要的字符的工具。 输出格式是TouchGFX应用使用的内部C++格式。 该工具是构建工具链不可或缺的一部分,将在构建模拟器时自动执行。

文本转换器接受

  • TrueType (.ttf)
  • OpenType (.otf)
  • Glyph Bitmap Distribution Format (.bdf).

只需将字体放在assets/fonts/文件夹中,TouchGFX Designer就可以引用该字体(如果在TouchGFX Designer运行时添加字体,必须重启软件才能更新可用字体)

在TouchGFX Designer中,还可以使用Windows操作系统中安装的字体,选择这些字体中的任何字体,它们就会被自动添加到assets/fonts/文件夹

字体转换器使用提供的字体中的字距调整信息进行字距调整。

Note
  • 使用TouchGFX并不以任何形式提供任何TrueType、OpenType或Bitmap字体的商业使用许可。
  • 字体转换器的输出目录为generated/fonts/。
  • 字符存储空间优化

    TouchGFX为减少存储空间消耗而进行了优化。 通过分析对特定字体排印使用的字符,将生成的字符(内部C++格式)数量最大限度压缩至应用实际使用的字符。

    另外,通过在文本配置中启用重新映射文本的选项,压缩使用常用后缀的文本,从而优化文本存储空间消耗量。

    通配符

    TouchGFX可将动态值作为文本的一部分来使用。 这可以通过在文本中使用通配符来实现。 按给定格式<*>指定通配符,其中的*表示不会包含在结果文本中的可选辅助文本。 一个文本中可以有至多2个通配符。

    给定文本的所有翻译文件必须包含相同数量的通配符。 通配符值在运行时被插入到C++代码中。

    通配符使用示例:温度为 <insert_temperature>°

    要注意的一个细节是,由于字符存储空间优化(参见上一节),只为特定字体排印生成了采用此字体排印的文本中使用的字符。 为强制字体生成器包含特定字符,您可以对每种字体排印使用“通配符字符”和“字符范围”。

    像下面这样使用反斜杠记号可以避免通配符格式<*>\<not a wildcard\>. 这会导致应用中使用原义文本 “<not a wildcard>” 。

    在TouchGFX Designer中使用通配符

    在TouchGFX Designer中,可以将通配符添加到常规TextArea。 现在,尽管TouchGFX中生成代码的方式并无变化,但有效地让TextArea控件覆盖了之前被TextAreaWithOneWildcard/TextAreaWithTwoWildcards控件覆盖的功能。

    在TouchGFX Designer中,您可以将通配符添加到TextArea,方法是使用常用语法 <*>或简单地点击所选TextArea的属性中的“添加通配符”按钮。 一个熟悉的示例是将温度读数添加到TextArea,可显示为温度为 °。 这种情况下可能是室外温度读数。 下面我们要插入一个通配符,不仅显示静态数值,还将根据温度读数进行更新。 通配符会被添加到文本中插入点光标的当前位置:

    将通配符添加到Text Area控件

    现在,属性中的文本将显示“温度为<value>°”,而画布上的文本显示“温度为°:”

    TouchGFX Designer中带通配符的Text Area控件

    为了设置特定的通配符,您可以点击相应的“通配符”按钮(本例中为通配符1),就可以编辑刚才添加的通配符。

    在这里,您可以选择如何更新通配符。 要么通过预定义资源文本,要么通过动态运行时间创建的文本。 在两种情况下,都可以在运行时间更新文本。 对于后者,需要一个通配符缓冲区用于存储动态文本。 这样的缓冲区可通过选中通配符缓冲区复选框来创建。 在这种情况下,还需要指定缓冲区大小(字符数)。 如果想要高效地利用存储空间,需使指定大小尽可能接近实际需要的文本大小。 记住,为字符串结束符(“\0”)增加一个额外空格。

    另外,还可以为通配符设置初始值,这样可以看到包含温度读数的TextArea的最终外观。 设置初始值会在文本数据库中创建硬编码一次性使用文本,或者如果选择了使用通配符缓冲区,则将其插入通配符缓冲区:

    TouchGFX Designer中的通配符设置

    在用户代码中使用通配符

    还可通过用户代码添加和更新通配符,如下面的代码示例所示,Unicode::UnicodeChar阵列在用户代码中进行管理和更新。

    gui/include/gui/some_screen/SomeView.hpp
    #include <touchgfx/widgets/TextAreaWithWildcard.hpp>
    ...
    class SomeView : public View<SomePresenter>
    {
    TextAreaWithOneWildcard txt;
    Unicode::UnicodeChar txtBuffer[10];
    }
    gui/src/some_screen/SomeView.cpp
    #include <texts/TextKeysAndLanguages.hpp>
    #include <touchgfx/Color.hpp>

    void SomeView::setupScreen()
    {
    txt.setTypedText(TypedText(T_TEMPERATURE_READOUT));
    txt.setXY(10, 20);
    txt.setColor(Color::getColorFrom24BitRGB(0xFF, 0xFF, 0xFF))
    txt.setWildcard(txtBuffer);
    add(txt);

    updateTxt(5);
    }

    void SomeView::updateTxt(int newValue)
    {
    Unicode::snprintf(txtBuffer, 10, "%d", newValue);
    txt.invalidate();
    }

    文本放置

    对于所有TouchGFX控件,通过指定位置(X和Y)和尺寸(宽和高)将TextArea放置到屏幕上。 可以在TouchGFX Designer的控件属性中轻松做到这一点,但是与TouchGFX渲染文本相比,TouchGFX Designer中的文本渲染并非总是100%准确。

    本节还描述了在处理文本时要注意的更多细节和可能性。

    对齐

    按照为文本数据库中选中文本条目指定的对齐方式对齐TextArea中的文本。 文本对齐是就TextArea的区域而言。 在下面的屏幕截图中,TextArea的区域高亮显示为蓝色。

    左对齐文本

    中心对齐文本

    右对齐文本

    这些设置可以在TouchGFX Designer的文本视图中进行设置。

    设置TextArea的正确宽度和高度

    TextArea能够根据目前选择的文本调整其宽度和高度。 这是通过调用TextArea::resizeToCurrentText()方法来完成的。

    Note
    resizeToCurrentText() resizeToCurrentText()会被自动调用,前提是在实例化具有新TypedText的TextArea时没有设置宽度和高度。

    在使用中心/右对齐文本时,通常不希望调整宽度和高度,因为文本需要在固定区域内实现中心/右对齐。 在这种情况下,可以手动设置宽度和高度。 这可以通过调用TextArea::setPosition(x, y, width, height)TextArea::setWidth(width)TextArea::setHeight(height)来完成。

    如果宽度和/或高度过小,无法容纳文本,将按照区域剪切文本,如下图所示。

    被 TextArea边界裁剪的文本

    为TextArea设置正确的X和Y值

    为了将TextArea放在正确的X和Y位置,需注意使用的字体的字符上方会有一些额外的间隔,可以容纳大字符。 由于不知道文本上方的具体间隔,使得根据左上角的Y位置放置TextArea变得有点困难。 放置文本的一种方式是指定您认为它应当处于的位置,然后通过在模拟器中检查放置效果来进行微调。 这通常是一项十分简单的任务,但如果之后更改字体或字号,则需要重新执行。

    一种更稳健的方式是使用文本基线。 基线是一条线,大多数字母“坐”在基线上,而下行字母(像p和j这样的字符)会延伸到基线之下。

    文本基线

    为了设置文本基线,可使用TextArea::setBaselineY(y)TextArea::setXBaselineY(x, y)。 对于这些方法,不指定TextArea的左上角,而是指定第一个文本行的基线。 这会考虑字号和间距,并相应地设置TextArea的Y位置。

    由于通过TouchGFX Designer画布可以轻松地放置TextArea控件,因此TouchGFX Designer中没有基线功能,只能在用户代码中使用。

    Note
    由于setBaselineY依赖于字体,TextArea需在调用setBaselineY之前设置其TypedText。 另外还要注意, 如果将TextAreas TypedText 修改为采用其他字体或字号,则需要再次调用setBaselineY

    长文本行的自动换行

    TextArea有时需要包含极长的文本。 默认情况下,只需将此类文本写成一行,并直接将超出TextArea的所有文本剪切掉。 如果文本应在空格处换行并回流以便形成多行,只需调用:

    myTextArea.setWideTextAction(WIDE_TEXT_WORDWRAP); // Default is WIDE_TEXT_NONE

    可用宽文本操作

    • WIDE_TEXT_NONE: 只需从超出TextArea宽度的任何字符的中间切割文本,无需其他操作。
    • WIDE_TEXT_WORDWRAP: 在字之间换行,在任意位置添加省略号“Very long t...”。
    • WIDE_TEXT_WORDWRAP_ELLIPSIS_AFTER_SPACE: 在字之间换行,只在空格后的任意位置添加省略号“Very long ...”。
    • WIDE_TEXT_CHARWRAP: 在任意两个字符之间换行,按照中文中的用法在任意位置添加省略号。
    • WIDE_TEXT_CHARWRAP_DOUBLE_ELLIPSIS:在任意两个字符之间换行,按照中文中的用法在任意位置添加双省略号。

    这可能会使TextArea需要更多垂直空间。 可通过增加TouchGFX Designer中TextArea的高度或在用户代码中用以下代码来实现。

    myTextArea.setWidth(200);
    myTextArea.resizeHeightToCurrentText(); // Will set height by wrapping text at 200px long lines
    myTextArea.invalidate();

    如果您准备缩小文本区的尺寸,记得在调整 myTextArea 尺寸之前调用myTextArea.invalidate()。 如果没有,由于原文本区未被更小的新文本区覆盖,因此您会看到它的一部分。

    切换语言

    TouchGFX支持多语言界面。 可以更改界面当前使用的语言,方法是调用静态函数Texts::setLanguage:

    Texts::setLanguage(GB);

    GB位于LANGUAGES枚举(位于TextKeysAndLanguages.hpp中)中,如“文本转换器”一节中的示例所示。

    此次调用后,使所有显示文本的控件无效(或简单地使整个屏幕无效),它们将以新选择的语言显示文本。

    TouchGFX Designer中

    您可以在不同语言之间切换,以便测试所有翻译文件。 可从配置视图的常规部分执行此操作。 这里只需更改应用的启动语言,方法是更改选中语言。 需要先创建并翻译语言,然后才能在“配置”视图中选择它们。