鸿蒙Qt字体实战:消灭“豆腐块“乱码与自定义字体加载

1. 满屏的"豆腐块"

在将Qt应用移植到鸿蒙初期,我们经常遇到一个尴尬的问题:

英文字符显示正常,但中文字符全部变成了方框(俗称"豆腐块" / Tofu)。

或者,设计师提供的精美 ttf 字体,在代码里加载成功了,但界面上死活不显示。

2. 原因一:系统字体回退失败

Qt依赖 fontconfig 或底层系统的字体API来查找默认字体。

在鸿蒙精简版(Standard System)或某些开发板上,可能预装的字体有限,或者Qt无法自动映射到系统的HarmonyOS Sans

临时方案:

在代码中显式指定一个存在的字体家族。

cpp 复制代码
QApplication app(argc, argv);
QFont font = app.font();
font.setFamily("HarmonyOS Sans SC"); // 尝试系统默认字体名
app.setFont(font);

3. 原因二:自定义字体加载路径错误

更多情况是应用自带了字体文件(如 OpenSans.ttf),但加载失败。

错误代码:

cpp 复制代码
int id = QFontDatabase::addApplicationFont(":/fonts/OpenSans.ttf"); // qrc路径
if (id == -1) {
    qWarning() << "Failed to load font"; // 鸿蒙上这里可能返回-1
}

虽然Qt通常支持从qrc加载字体,但在某些嵌入式或移动平台配置下,Qt需要一个物理文件路径来创建FreeType引擎的句柄。

解决方案:拷贝+加载

策略与Rawfile资源类似,先将字体文件拷贝到沙箱可写目录,再加载。

cpp 复制代码
QString fontPath = copyRawFileToSandbox("myfont.ttf");
int id = QFontDatabase::addApplicationFont(fontPath);

if (id != -1) {
    QString family = QFontDatabase::applicationFontFamilies(id).at(0);
    QFont font(family);
    app.setFont(font);
}

4. 进阶:Qt Quick 中文字体失效

在QML中,你可能设置了:

qml 复制代码
Text {
    font.family: "MyCustomFont"
    text: "你好"
}

但显示依然是默认字体。

这通常是因为 FontLoader 的使用方式不对。

正确姿势:

qml 复制代码
FontLoader {
    id: localFont
    source: "file:///data/storage/.../myfont.ttf" // 使用绝对路径
}

Text {
    font.family: localFont.name // 必须引用FontLoader的name属性
    text: "Hello"
}

最佳实践:

尽量使用 qrc:/ 加载 QML 中的字体资源,如果遇到平台兼容性问题(FreeType报错),再回退到本地文件方案。

5. 字体渲染模糊?High DPI适配

如果字体加载出来了,但是边缘锯齿严重或者模糊。

检查 main.cpp 是否开启了High DPI支持。

cpp 复制代码
// Qt 6 默认开启,但在某些鸿蒙设备上可能获取的DPR不对
app.setAttribute(Qt::AA_UseHighDpiPixmaps);

// 手动强制DPR(如果系统识别错误)
qputenv("QT_SCALE_FACTOR", "2"); 

6. 总结

  1. 中文乱码 :通常是系统字体映射失败,建议打包开源的中文字体(如 Source Han Sans 的精简版)随App发布。
  2. 加载失败addApplicationFontqrc 支持不稳定时,拷贝到临时目录再加载。
  3. QML字体 :使用 FontLoader 并正确引用 .name 属性。

字体是UI的门面,解决好字体问题,应用的质感瞬间提升一个档次。

相关推荐
SilentSlot39 分钟前
【QT-QML】5. 简单变换
qt·qml
xiaoqi9222 小时前
React Native鸿蒙跨平台如何实现分类页面组件通过searchQuery状态变量管理搜索输入,实现了分类的实时过滤功能
javascript·react native·react.js·ecmascript·harmonyos
听麟2 小时前
HarmonyOS 6.0+ 智慧出行导航APP开发实战:离线地图与多设备位置协同落地
华为·wpf·harmonyos
qq_177767372 小时前
React Native鸿蒙跨平台实现应用介绍页,实现了应用信息卡片展示、特色功能网格布局、权限/联系信息陈列、评分展示、模态框详情交互等通用场景
javascript·react native·react.js·ecmascript·交互·harmonyos
jin1233224 小时前
基于React Native鸿蒙跨平台地址管理是许多电商、外卖、物流等应用的重要功能模块,实现了地址的添加、编辑、删除和设置默认等功能
javascript·react native·react.js·ecmascript·harmonyos
2501_920931704 小时前
React Native鸿蒙跨平台医疗健康类的血压记录,包括收缩压、舒张压、心率、日期、时间、备注和状态
javascript·react native·react.js·ecmascript·harmonyos
2501_920931705 小时前
React Native鸿蒙跨平台使用useState管理健康记录和过滤状态,支持多种健康数据类型(血压、体重等)并实现按类型过滤功能
javascript·react native·react.js·ecmascript·harmonyos
2501_921930835 小时前
高级进阶 React Native 鸿蒙跨平台开发:InteractionManager 交互优化
react native·harmonyos
前端不太难6 小时前
HarmonyOS PC 文档模型完整范式
华为·状态模式·harmonyos
ITUnicorn7 小时前
【HarmonyOS6】从零实现自定义计时器:掌握TextTimer组件与计时控制
华为·harmonyos·arkts·鸿蒙·harmonyos6