📖 目录一、鸿蒙字体简介

二、环境准备与字体获取

三、方法一:C++ 全局加载(推荐)

四、方法二:QML 局部加载(备选)

五、在 QML 控件中统一应用鸿蒙字体

六、常见问题与解决方案

七、总结

一、鸿蒙字体简介

鸿蒙操作系统搭载的 HarmonyOS Sans 是一款无级可变字体,支持中文、英文、数字等多种语言,字形现代、可读性高。在 Qt/QML 应用中使用该字体,可让界面风格与 HarmonyOS 生态保持一致,尤其适合在鸿蒙设备上运行的应用程序。

核心优势

  • 开源免费:华为官方开源,可商用,无版权风险
  • 多字重支持:包含 Regular、Bold、Light 等,满足标题 / 正文 / 注释等不同场景
  • 跨平台:可在 Windows、Linux、鸿蒙等系统中无缝使用

二、环境准备与字体获取

2.1 下载鸿蒙字体

访问华为官方开源社区:HarmonyOS 字体下载下载字体包(通常包含 HarmonyOS_Sans_SC_Regular.ttf、HarmonyOS_Sans_SC_Bold.ttf 等)。将字体文件放入 Qt 项目目录,建议创建专门的 fonts/ 文件夹存放(如 项目根目录/fonts/)。

2.2 将字体添加到资源文件(.qrc)

在 Qt Creator 中创建或编辑 .qrc 文件(如 resource.qrc),添加字体资源:

xml

<RCC>
    <qresource prefix="/fonts">
        <file>fonts/HarmonyOS_Sans_SC_Regular.ttf</file>
        <file>fonts/HarmonyOS_Sans_SC_Bold.ttf</file>
    </qresource>
</RCC>

⚠️ 关键:若使用 qmake 构建,需在 .pro 文件中添加资源引用:

bash

运行

RESOURCES += resource.qrc

三、方法一:C++ 全局加载(推荐)

main.cpp 中通过 QFontDatabase 全局注册字体,一次加载全应用可用,无异步问题,是生产环境首选方案。

3.1 完整代码示例

cpp

运行

#include <QGuiApplication>    // Qt GUI应用程序核心头文件,用于创建GUI应用
#include <QQmlApplicationEngine> // QML引擎头文件,用于加载和运行QML界面
#include <QFontDatabase>      // 字体数据库头文件,用于加载和管理自定义字体
#include <QDebug>             // 调试输出头文件,用于打印日志信息

int main(int argc, char *argv[])
{
    // ===================== 初始化配置 =====================
    // 启用高DPI缩放适配(可选)
    // 作用:提升在高分屏、鸿蒙设备等高清显示设备上的字体/界面显示效果
    QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);

    // 创建Qt GUI应用程序对象,管理应用程序的生命周期和事件循环
    QGuiApplication app(argc, argv);

    // ===================== 加载鸿蒙常规字体 =====================
    // 1. 拼接字体文件路径:应用程序运行目录 + fonts文件夹 + 常规字体文件名
    // applicationDirPath():获取当前程序的运行目录(如debug/、release/)
    QString fontPath = QCoreApplication::applicationDirPath() + "/fonts/HarmonyOS_SansSC_Regular.ttf";

    // 2. 加载字体文件到应用程序的字体数据库
    // addApplicationFont():返回字体ID(-1表示加载失败)
    int fontId = QFontDatabase::addApplicationFont(fontPath);

    // 调试输出:打印字体路径,方便排查路径错误
    qWarning() << "fontpath:" << fontPath;

    // 3. 检查字体是否加载成功,并获取字体族名(QML中必须使用该名称)
    if (fontId != -1) {
        // 获取加载成功的字体族名列表(通常只有一个)
        QStringList fontFamilies = QFontDatabase::applicationFontFamilies(fontId);
        // 打印成功日志和字体族名(关键:QML中要严格匹配这个名称)
        qDebug() << "✅ 鸿蒙常规字体加载成功,族名:" << fontFamilies;
        // 输出示例:("HarmonyOS Sans SC")
    } else {
        // 加载失败时打印错误日志,提示检查路径
        qWarning() << "❌ 鸿蒙常规字体加载失败,请检查资源路径!";
    }

    // ===================== 加载鸿蒙粗体字体 =====================
    // 1. 拼接粗体字体文件路径(和常规字体同目录)
    fontPath = QCoreApplication::applicationDirPath() + "/fonts/HarmonyOS_SansSC_Bold.ttf";
    // 2. 加载粗体字体文件
    int boldFontId = QFontDatabase::addApplicationFont(fontPath);

    // 3. 检查粗体字体加载状态
    if (boldFontId == -1) {
        // 粗体加载失败时打印警告(不影响主流程,仅提示)
        qWarning() << "⚠️ 鸿蒙粗体字体加载失败,请检查粗体字体文件路径!";
    } else {
        // 可选:打印粗体字体族名(通常和常规字体族名一致,仅字重不同)
        QStringList boldFontFamilies = QFontDatabase::applicationFontFamilies(boldFontId);
        qDebug() << "✅ 鸿蒙粗体字体加载成功,族名:" << boldFontFamilies;
    }

    // ===================== 加载QML界面 =====================
    // 创建QML引擎对象
    QQmlApplicationEngine engine;
    // 加载主QML文件(资源路径方式,确保打包后能正常访问)
    engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

    // ===================== 启动应用事件循环 =====================
    // 进入应用程序的主事件循环,处理用户交互、界面刷新等事件
    // 没有这一行,程序会加载完成后直接退出
    return app.exec();
}

3.2 关键说明

  • addApplicationFont() 返回 -1 表示加载失败,优先检查:
    1. 字体文件路径是否与 .qrc 中一致
    2. 字体文件是否损坏(重新下载官方包)
    3. .pro 文件是否正确包含 RESOURCES
  • 字体族名以 qDebug 输出为准(通常是 HarmonyOS Sans SC),QML 中必须完全匹配
  • 全局加载后,所有 QML/C++ 控件无需额外处理即可直接使用

四、方法二:QML 局部加载(备选)

若无法修改 C++ 代码(如仅能编辑 QML),可使用 FontLoader 动态加载,但需处理异步加载问题。

4.1 基础用法(带状态监听)

qml

import QtQuick 2.6
import QtQuick.Window 2.2

Window {
    visible: true
    width: 500
    height: 400
    title: "鸿蒙字体 vs 宋体 对比测试"

    // 标题说明
    Text {
        anchors.top: parent.top
        anchors.topMargin: 10
        anchors.horizontalCenter: parent.horizontalCenter
        text: "字体效果对比"
        font.pixelSize: 18
        font.bold: true
    }

    // 第一组:鸿蒙常规字体
    Text {
        anchors.top: parent.top
        anchors.topMargin: 50
        anchors.horizontalCenter: parent.horizontalCenter
        text: "鸿蒙常规字体:Hello 鸿蒙字体测试 123"
        font.family: "HarmonyOS Sans SC"  // 鸿蒙字体族名
        font.pixelSize: 24
        color: "#007DFF"  // 蓝色区分
    }

    // 第二组:鸿蒙粗体字体
    Text {
        anchors.top: parent.top
        anchors.topMargin: 90
        anchors.horizontalCenter: parent.horizontalCenter
        text: "鸿蒙粗体字体:Hello 鸿蒙字体测试 123"
        font.family: "HarmonyOS Sans SC"
        font.pixelSize: 24
        font.bold: true
        color: "#007DFF"
    }

    // 分割线
    Rectangle {
        anchors.top: parent.top
        anchors.topMargin: 140
        anchors.horizontalCenter: parent.horizontalCenter
        width: 450
        height: 1
        color: "#E5E5E5"
    }

    // 第三组:宋体常规
    Text {
        anchors.top: parent.top
        anchors.topMargin: 160
        anchors.horizontalCenter: parent.horizontalCenter
        text: "宋体常规字体:Hello 鸿蒙字体测试 123"
        font.family: "SimSun"  // 宋体的英文族名(跨平台通用)
        font.pixelSize: 24
        color: "#FF6600"  // 橙色区分
    }

    // 第四组:宋体粗体
    Text {
        anchors.top: parent.top
        anchors.topMargin: 200
        anchors.horizontalCenter: parent.horizontalCenter
        text: "宋体粗体字体:Hello 鸿蒙字体测试 123"
        font.family: "SimSun"
        font.pixelSize: 24
        font.bold: true
        color: "#FF6600"
    }

    // 补充说明:字体族名提示
    Text {
        anchors.bottom: parent.bottom
        anchors.bottomMargin: 20
        anchors.horizontalCenter: parent.horizontalCenter
        text: "HarmonyOS Sans SC (鸿蒙) | SimSun (宋体)"
        font.pixelSize: 12
        color: "#666666"
    }
}

4.2 解决异步加载闪烁问题

FontLoader 加载是异步的,首次渲染可能显示默认字体,可通过以下方式优化:

qml

// 延迟显示文本,直到字体加载完成
Text {
    anchors.centerIn: parent
    text: "鸿蒙字体示例"
    font.family: harmonyFont.name
    font.pixelSize: 24
    // 初始隐藏,加载完成后显示
    visible: harmonyFont.status === FontLoader.Ready
}

// 或添加过渡动画
Text {
    anchors.centerIn: parent
    text: "鸿蒙字体示例"
    font.family: harmonyFont.status === FontLoader.Ready ? harmonyFont.name : "Arial"
    font.pixelSize: 24
    opacity: harmonyFont.status === FontLoader.Ready ? 1 : 0
    Behavior on opacity { NumberAnimation { duration: 300 } }
}

五、在 QML 控件中统一应用鸿蒙字体

5.1 基础文本控件(通用)

qml

// 普通文本
Text {
    text: "用户名"
    font.family: "HarmonyOS Sans SC"  // 与C++输出的族名一致
    font.pixelSize: 14
}

// 粗体文本
Text {
    text: "标题文本"
    font.family: "HarmonyOS Sans SC"
    font.pixelSize: 18
    font.bold: true  // 使用粗体字重
}

// 输入框
TextInput {
    width: 200
    font.family: "HarmonyOS Sans SC"
    font.pixelSize: 14
    placeholderText: "请输入手机号"
}

// 多行文本
TextEdit {
    width: 200
    height: 100
    font.family: "HarmonyOS Sans SC"
    font.pixelSize: 14
    text: "多行文本编辑示例"
}

5.2 复杂控件(ComboBox/CheckBox)

Qt 5.6.3 中部分控件对 font 属性支持有限,推荐方案:

qml

// ComboBox(兼容写法)
ComboBox {
    width: 200
    // 直接设置可能无效,优先全局加载后依赖继承
    font.family: "HarmonyOS Sans SC"
    font.pixelSize: 12
    model: ["选项1", "选项2", "选项3"]
    
    // 若无效,自定义下拉项文本样式
    delegate: Item {
        width: parent.width
        height: 30
        Text {
            anchors.centerIn: parent
            text: modelData
            font.family: "HarmonyOS Sans SC"
            font.pixelSize: 12
        }
    }
}

// CheckBox
CheckBox {
    text: "同意用户协议"
    // 直接设置主文本字体
    font.family: "HarmonyOS Sans SC"
    font.pixelSize: 12
}

5.3 全局统一样式(推荐)

在根组件设置默认字体,减少重复代码:

qml

Window {
    id: rootWindow
    visible: true
    width: 800
    height: 600
    // 全局字体族,子控件默认继承
    font.family: "HarmonyOS Sans SC"
    font.pixelSize: 14

    // 子控件自动继承,无需重复设置
    Text {
        text: "自动使用全局鸿蒙字体"
        // 仅需设置差异化属性
        font.pixelSize: 16
    }
}

六、常见问题与解决方案

Q1:字体加载后 QML 中显示为默认字体?

原因:C++ 加载的字体族名称与 QML 中使用的名称不匹配。
解决:在 main.cpp 中 qDebug() 输出实际族名,例如 "HarmonyOS Sans SC",然后在 QML 中使用该名称。

Q2:QML 中使用 FontLoader 时,文字闪烁或短暂显示默认字体?

原因:字体加载是异步的,初始时 FontLoader.name 为空。
解决:使用绑定 font.family: harmonyFont.status === FontLoader.Ready ? harmonyFont.name : "Arial",或预加载字体(如提前创建不可见的 Text 触发加载)。

Q3:ComboBox 或 CheckBox 的字体无法设置为鸿蒙字体?

原因:Qt 5.6.3 中部分控件对 font 属性的支持不稳定。
解决:使用 C++ 全局加载后,这些控件通常会继承系统默认字体。若仍需强制修改,可考虑自定义控件(如 Rectangle + Text + MouseArea 模拟下拉框)。

Q4:打包发布后字体丢失?

原因:字体资源未正确包含在可执行文件目录或安装包中。
解决:确保 .qrc 文件已编译进程序,或者将字体文件作为外部文件随应用发布,并在代码中使用绝对路径加载。

Q5:C++ 加载返回 -1,提示 Failed to load?

原因:字体文件路径错误、文件名大小写不匹配、资源未编译、文件损坏。
解决

  • 检查 .qrc 中的路径与代码中的字符串是否完全一致(包括大小写)。有的是"/fonts/HarmonyOS_Sans_SC_Regular.ttf"或者"/fonts/HarmonyOS_SansSC_Regular.ttf"以实际路径文件名字为准。

  • 在 Qt Creator 中右键 .qrc → Run qmake,重新编译资源。

  • 用绝对路径测试字体文件是否有效。

  • 确认字体文件本身未损坏。

七、总结

✨ 核心要点

  1. 推荐方案:C++ 全局加载(QFontDatabase::addApplicationFont),一次加载全应用可用,无异步问题;
  2. 关键细节:字体族名必须与 applicationFontFamilies 输出一致(通常为 HarmonyOS Sans SC);
  3. 兼容处理:Qt 5.6.3 复杂控件(ComboBox/CheckBox)优先通过自定义文本样式适配,避免直接设置 font 属性失效;
  4. 发布注意:确保字体资源通过 .qrc 打包进应用,避免外部依赖丢失。

🎯 最佳实践

  • 生产环境优先使用 C++ 全局加载,简化 QML 代码,避免异步问题;
  • 全局设置根组件字体族,减少重复代码;
  • 测试阶段通过 qDebug/console.log 验证字体加载状态,提前发现路径 / 名称错误;
  • 鸿蒙设备上配合高 DPI 适配(AA_EnableHighDpiScaling),提升字体显示效果。

按照本教程操作,你可以轻松在 Qt 5.6.3 QML 应用中集成鸿蒙字体,让界面风格与 HarmonyOS 生态无缝融合,无论是开发鸿蒙设备应用还是跨平台应用,都能获得统一、美观的字体显示效果!

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐