QT中使用第三方字体库(比如:思源黑体等)

阿里云教程3个月前发布
16 0 0

一、思源黑体

思源黑体是一款由 Adobe 与 Google 合作领导开发的开源中文黑体字型。它的发布是字体界的一个里程碑事件,因为它提供了一款高质量、完全免费且可商用的现代黑体。

中文名称: 思源黑体

英文/日文名称: Source Han Sans / Noto Sans CJK

开发者: Adobe, Google

授权: 开源 (SIL Open Font License 1.1)

设计风格: 现代、无衬线

主要特点

开源免费
这是思源黑体最核心的特点。无论是个人使用、商业项目还是嵌入到APP或网站上,都无需支付任何授权费用。这极大地降低了设计师和开发者的成本。

字重齐全
思源黑体提供了从 ExtraLight 到 Heavy 共7种字重,满足了从正文到标题的各种排版需求。

ExtraLight, Light, Normal / Regular, Medium, SemiBold / DemiBold, Bold, Heavy

字符集巨大
它支持中国(简/繁)、日本、韩国等地区的汉字,以及拉丁文、希腊文、西里尔文字母,几乎涵盖了所有使用场景。单个字型的字符数量超过5万个,确保了在不同语言环境下的显示一致性。

设计精良
由顶尖的字体设计师团队打造,字形清晰、中性、现代,阅读体验舒适。它继承了经典黑体的结构,但在笔画末端和转折处做了更柔和的处理,使其在屏幕上显示效果更佳。

多语言子集
为了方便不同地区的用户,思源黑体发布了针对特定语言区域的子集版本,例如:

Source Han Sans SC (简体中文)

Source Han Sans TC (繁体中文)

Source Han Sans HK (香港繁体)

Source Han Sans JP (日文)

Source Han Sans KR (韩文)

如何获取与使用

1. 官方下载地址:

Adobe (Source Han Sans): https://github.com/adobe-fonts/source-han-sans

Google (Noto Sans CJK): https://www.google.com/get/noto/

2. 在操作系统中安装:
下载后,解压文件,选择您需要的语言版本和字重(通常是OTF或TTF文件),右键点击并选择“为所有用户安装”或“安装”。

OTF 和 TTF 是两种主流的字体文件格式,它们之间有一些关键区别,会影响字体在显示和打印时的效果。简单来说:

OTF(OpenType) 功能更强大,是现代字体技术的首选。

TTF(TrueType) 兼容性极佳,是经典的字体格式。

中文思源黑体字体库下载地址

字重的独立文件
SimplifiedChinese/SourceHanSansSC-Light.otf
SimplifiedChinese/SourceHanSansSC-Regular.otf
SimplifiedChinese/SourceHanSansSC-Medium.otf
SimplifiedChinese/SourceHanSansSC-Bold.otf
SimplifiedChinese/SourceHanSansSC-Heavy.otf

可变字体的字重范围
思源黑体 VF 支持的字重范围通常是:200 到 900
SourceHanSansSC-VF.ttf

二、Qt中使用新字体

方法一(安装字体到系统font目录下)

安装字体到系统font目录下,通过右键点击字体文件安装,安装后,重启Qt Creator,在UI编辑器中就可以使用该字体了。

可以判断系统中是否包含该字体,如果不包含,就通过bat脚本安装字体到系统font目录下,或者程序自身检测和安装字体。

方案 1:使用批处理脚本 + Qt 程序

1. 主批处理脚本 
install_fonts.bat(utf-8格式,防止乱码)

batch

@echo off
chcp 65001 >nul
title 思源黑体字体安装程序
setlocal enabledelayedexpansion

REM ===============================================
REM 思源黑体批量安装脚本
REM 版本: 2.0
REM ===============================================

set "SCRIPT_DIR=%~dp0"
set "FONTS_DIR=%SCRIPT_DIR%fonts"
set "SYSTEM_FONTS=%WINDIR%Fonts"
set "REG_PATH=HKLMSOFTWAREMicrosoftWindows NTCurrentVersionFonts"

REM 颜色定义
for /f "delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do set "DEL=%%a"
echo.
call :color 0A & echo ===============================================
call :color 0A & echo           思源黑体批量安装程序
call :color 0A & echo ===============================================
echo.

REM 检查管理员权限
call :check_admin
if errorlevel 1 (
    call :color 0C & echo 错误: 需要管理员权限运行此脚本
    call :color 0E & echo 请右键点击,选择"以管理员身份运行"
    echo.
    pause
    exit /b 1
)

REM 检查字体目录
if not exist "%FONTS_DIR%" (
    call :color 0C & echo 错误: 字体目录不存在: %FONTS_DIR%
    echo.
    pause
    exit /b 1
)

REM 字体配置列表
set "FONT_COUNT=0"
set "FONT_LIST[0].FILE=SourceHanSansSC-Light.otf"
set "FONT_LIST[0].NAME=Source Han Sans SC Light"
set "FONT_LIST[0].REG_NAME=Source Han Sans SC Light (OpenType)"

set "FONT_LIST[1].FILE=SourceHanSansSC-Regular.otf"
set "FONT_LIST[1].NAME=Source Han Sans SC"
set "FONT_LIST[1].REG_NAME=Source Han Sans SC (OpenType)"

set "FONT_LIST[2].FILE=SourceHanSansSC-Medium.otf"
set "FONT_LIST[2].NAME=Source Han Sans SC Medium"
set "FONT_LIST[2].REG_NAME=Source Han Sans SC Medium (OpenType)"

set "FONT_LIST[3].FILE=SourceHanSansSC-Bold.otf"
set "FONT_LIST[3].NAME=Source Han Sans SC Bold"
set "FONT_LIST[3].REG_NAME=Source Han Sans SC Bold (OpenType)"

set "FONT_LIST[4].FILE=SourceHanSansSC-Heavy.otf"
set "FONT_LIST[4].NAME=Source Han Sans SC Heavy"
set "FONT_LIST[4].REG_NAME=Source Han Sans SC Heavy (OpenType)"

set "FONT_TOTAL=5"

REM 显示安装信息
call :color 0B & echo 安装信息:
call :color 0F & echo   字体目录: %FONTS_DIR%
call :color 0F & echo   系统字体目录: %SYSTEM_FONTS%
call :color 0F & echo   安装字体数量: %FONT_TOTAL%
echo.

REM 确认安装
call :color 0E & echo 是否继续安装?(Y/N)
choice /c YN /n >nul
if errorlevel 2 (
    call :color 0E & echo 安装已取消
    timeout /t 2 >nul
    exit /b 0
)

echo.
call :color 0A & echo 开始安装字体...
echo.

REM 安装字体
set "SUCCESS_COUNT=0"
set "FAILED_COUNT=0"

for /l %%i in (0,1,4) do (
    set "FONT_FILE=!FONT_LIST[%%i].FILE!"
    set "FONT_NAME=!FONT_LIST[%%i].NAME!"
    set "REG_NAME=!FONT_LIST[%%i].REG_NAME!"
    
    call :install_font "!FONT_FILE!" "!FONT_NAME!" "!REG_NAME!"
    if !errorlevel! equ 0 (
        set /a "SUCCESS_COUNT+=1"
    ) else (
        set /a "FAILED_COUNT+=1"
    )
)

REM 刷新字体缓存
call :refresh_font_cache

REM 显示安装结果
echo.
call :color 0A & echo ===============================================
call :color 0A & echo                   安装完成
call :color 0A & echo ===============================================
echo.
call :color 0F & echo 安装统计:
call :color 0A & echo   成功: %SUCCESS_COUNT%
if %FAILED_COUNT% gtr 0 (
    call :color 0C & echo   失败: %FAILED_COUNT%
) else (
    call :color 0A & echo   失败: %FAILED_COUNT%
)

echo.
if %SUCCESS_COUNT% equ %FONT_TOTAL% (
    call :color 0A & echo 所有字体安装成功!
) else if %SUCCESS_COUNT% gtr 0 (
    call :color 0E & echo 部分字体安装成功,请检查失败的字体。
) else (
    call :color 0C & echo 所有字体安装失败!
)

REM 启动Qt应用程序
if exist "%SCRIPT_DIR%YourQtApp.exe" (
    echo.
    call :color 0B & echo 启动Qt应用程序...
    start "" "%SCRIPT_DIR%YourQtApp.exe"
    call :color 0A & echo 应用程序已启动
)

echo.
call :color 0E & echo 按任意键退出...
pause >nul
exit /b 0

REM ===============================================
REM 函数定义
REM ===============================================

:check_admin
REM 检查管理员权限
net session >nul 2>&1
if %errorlevel% equ 0 (
    exit /b 0
) else (
    exit /b 1
)

:install_font
REM 安装单个字体
REM 参数: %1=字体文件, %2=字体名称, %3=注册表名称
setlocal
set "FONT_FILE=%~1"
set "FONT_NAME=%~2"
set "REG_NAME=%~3"
set "SOURCE_PATH=%FONTS_DIR%\%FONT_FILE%"
set "DEST_PATH=%SYSTEM_FONTS%\%FONT_FILE%"

call :color 0F & echo 正在安装: %FONT_NAME%

REM 检查源文件
if not exist "%SOURCE_PATH%" (
    call :color 0C & echo   错误: 字体文件不存在 - %FONT_FILE%
    endlocal & exit /b 1
)

REM 检查是否已安装
reg query "%REG_PATH%" /v "%REG_NAME%" >nul 2>&1
if %errorlevel% equ 0 (
    call :color 0E & echo   提示: 字体已安装,跳过 - %FONT_NAME%
    endlocal & exit /b 0
)

REM 复制字体文件
call :color 0F & echo   复制字体文件...
copy "%SOURCE_PATH%" "%DEST_PATH%" >nul 2>&1
if errorlevel 1 (
    call :color 0C & echo   错误: 复制字体文件失败 - %FONT_FILE%
    endlocal & exit /b 1
)

REM 注册字体
call :color 0F & echo   注册字体到系统...
reg add "%REG_PATH%" /v "%REG_NAME%" /t REG_SZ /d "%FONT_FILE%" /f >nul 2>&1
if errorlevel 1 (
    call :color 0C & echo   错误: 注册字体失败 - %FONT_NAME%
    endlocal & exit /b 1
)

REM 验证安装
reg query "%REG_PATH%" /v "%REG_NAME%" >nul 2>&1
if errorlevel 1 (
    call :color 0C & echo   错误: 字体注册验证失败 - %FONT_NAME%
    endlocal & exit /b 1
)

call :color 0A & echo   成功: 字体安装完成 - %FONT_NAME%
endlocal & exit /b 0

:refresh_font_cache
REM 刷新字体缓存
call :color 0B & echo 刷新系统字体缓存...

REM 方法1: 使用 PowerShell 刷新字体缓存
powershell -Command "try { Add-Type -Name FontCache -Namespace Win32 -MemberDefinition '[DllImport("gdi32.dll")]public static extern int AddFontResource(string lpszFilename);' -PassThru; [Win32.FontCache]::AddFontResource('$env:WINDIR\Fonts\'); Write-Host '字体缓存刷新成功' -ForegroundColor Green } catch { Write-Host '字体缓存刷新失败: $($_.Exception.Message)' -ForegroundColor Red }" >nul 2>&1

REM 方法2: 使用 RUNDLL32 刷新
rundll32.exe gdi32.dll,AddFontResourceA "%SYSTEM_FONTS%" >nul 2>&1

call :color 0A & echo 字体缓存刷新完成
exit /b 0

:color
REM 颜色设置函数
echo %DEL% > "%~dp0color.tmp"
findstr /v /a:%1 /R "^$" "%~dp0color.tmp" nul
del "%~dp0color.tmp" >nul 2>&1
exit /b
2. 简化版本 
quick_install.bat
(无管理员权限检查)

batch

@echo off
chcp 65001 >nul
title 思源黑体快速安装

echo ================================
echo     思源黑体快速安装程序
echo ================================
echo.

set "FONTS_SOURCE=fonts"
set "FONTS_TARGET=%WINDIR%Fonts"

if not exist "%FONTS_SOURCE%" (
    echo 错误: 字体目录不存在
    pause
    exit /b 1
)

echo 正在安装思源黑体字体...
echo.

for %%F in ("%FONTS_SOURCE%SourceHanSansSC-*.otf") do (
    echo 安装: %%~nxF
    copy "%%F" "%FONTS_TARGET%" >nul 2>&1
    if errorlevel 1 (
        echo   失败: 请以管理员身份运行
    ) else (
        echo   成功
    )
)

echo.
echo 字体安装完成!
echo.
echo 按任意键退出...
pause >nul
3. 静默安装版本 
silent_install.bat

batch

@echo off
REM 思源黑体静默安装脚本
setlocal

set "FONTS_DIR=%~dp0fonts"
set "TARGET_DIR=%WINDIR%Fonts"
set "REG_PATH=HKLMSOFTWAREMicrosoftWindows NTCurrentVersionFonts"

REM 检查管理员权限(静默)
net session >nul 2>&1
if errorlevel 1 exit /b 1

REM 安装字体
for %%F in ("%FONTS_DIR%SourceHanSansSC-Light.otf") do (
    if exist "%%F" (
        copy "%%F" "%TARGET_DIR%" >nul 2>&1
        reg add "%REG_PATH%" /v "Source Han Sans SC Light (OpenType)" /t REG_SZ /d "%%~nxF" /f >nul 2>&1
    )
)

for %%F in ("%FONTS_DIR%SourceHanSansSC-Regular.otf") do (
    if exist "%%F" (
        copy "%%F" "%TARGET_DIR%" >nul 2>&1
        reg add "%REG_PATH%" /v "Source Han Sans SC (OpenType)" /t REG_SZ /d "%%~nxF" /f >nul 2>&1
    )
)

for %%F in ("%FONTS_DIR%SourceHanSansSC-Bold.otf") do (
    if exist "%%F" (
        copy "%%F" "%TARGET_DIR%" >nul 2>&1
        reg add "%REG_PATH%" /v "Source Han Sans SC Bold (OpenType)" /t REG_SZ /d "%%~nxF" /f >nul 2>&1
    )
)

for %%F in ("%FONTS_DIR%SourceHanSansSC-Heavy.otf") do (
    if exist "%%F" (
        copy "%%F" "%TARGET_DIR%" >nul 2>&1
        reg add "%REG_PATH%" /v "Source Han Sans SC Heavy (OpenType)" /t REG_SZ /d "%%~nxF" /f >nul 2>&1
    )
)

REM 启动应用程序
if exist "%~dp0YourQtApp.exe" (
    start "" "%~dp0YourQtApp.exe"
)

exit /b 0
4. 项目目录结构

text

应用程序目录/
├── fonts/
│   ├── SourceHanSansSC-Light.otf
│   ├── SourceHanSansSC-Regular.otf
│   ├── SourceHanSansSC-Medium.otf
│   ├── SourceHanSansSC-Bold.otf
│   └── SourceHanSansSC-Heavy.otf
├── install_fonts.bat      (主安装脚本)
├── quick_install.bat      (快速安装)
├── silent_install.bat     (静默安装)
└── YourQtApp.exe
使用方法:

双击运行:直接双击 
install_fonts.bat

管理员运行:右键选择”以管理员身份运行”

命令行运行:
install_fonts.bat


安装提示:输入y,进行安装。

方案 2:使用 Qt 程序自身检测和安装

2.1 创建字体安装工具类

cpp

// fontinstaller.h
#ifndef FONTINSTALLER_H
#define FONTINSTALLER_H

#include <QString>
#include <QProcess>

class FontInstaller
{
public:
    static bool isSourceHanSansInstalled();
    static bool installSourceHanSans();
    static QString getSystemFontDirectory();
    static bool copyFontToSystem(const QString &sourcePath);
    static bool registerFontInRegistry(const QString &fontFileName);
    static bool isAdminPrivileges();

private:
    static const QString FONT_NAME;
    static const QString FONT_FILE;
};

#endif // FONTINSTALLER_H
2.2 实现字体安装工具类

cpp

// fontinstaller.cpp
#include "fontinstaller.h"
#include <QDir>
#include <QFile>
#include <QFileInfo>
#include <QSettings>
#include <QCoreApplication>
#include <QDebug>
#include <windows.h>

const QString FontInstaller::FONT_NAME = "Source Han Sans SC";
const QString FontInstaller::FONT_FILE = "SourceHanSansSC-VF.ttf";

bool FontInstaller::isSourceHanSansInstalled()
{
    // 方法1: 检查注册表
    QSettings reg("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts", QSettings::NativeFormat);
    QString fontKey = FONT_NAME + " (TrueType)";
    return reg.contains(fontKey);
    
    // 方法2: 检查字体文件是否存在(备用)
    QString fontPath = getSystemFontDirectory() + "\" + FONT_FILE;
    return QFile::exists(fontPath);
}

QString FontInstaller::getSystemFontDirectory()
{
    wchar_t winDir[MAX_PATH];
    GetWindowsDirectory(winDir, MAX_PATH);
    return QString::fromWCharArray(winDir) + "\Fonts";
}

bool FontInstaller::copyFontToSystem(const QString &sourcePath)
{
    QString destPath = getSystemFontDirectory() + "\" + FONT_FILE;
    
    // 检查源文件是否存在
    if (!QFile::exists(sourcePath)) {
        qWarning() << "Source font file not found:" << sourcePath;
        return false;
    }
    
    // 复制字体文件
    if (QFile::copy(sourcePath, destPath)) {
        qDebug() << "Font copied successfully to:" << destPath;
        return true;
    } else {
        qWarning() << "Failed to copy font to system directory";
        return false;
    }
}

bool FontInstaller::registerFontInRegistry(const QString &fontFileName)
{
    QSettings reg("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts", QSettings::NativeFormat);
    QString fontKey = FONT_NAME + " (TrueType)";
    reg.setValue(fontKey, fontFileName);
    
    // 验证注册是否成功
    return reg.contains(fontKey);
}

bool FontInstaller::isAdminPrivileges()
{
    BOOL isAdmin = FALSE;
    PSID adminGroup = NULL;
    
    SID_IDENTIFIER_AUTHORITY ntAuthority = SECURITY_NT_AUTHORITY;
    
    if (AllocateAndInitializeSid(&ntAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID,
                                DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &adminGroup)) {
        if (!CheckTokenMembership(NULL, adminGroup, &isAdmin)) {
            isAdmin = FALSE;
        }
        FreeSid(adminGroup);
    }
    
    return isAdmin != FALSE;
}

bool FontInstaller::installSourceHanSans()
{
    // 检查是否已安装
    if (isSourceHanSansInstalled()) {
        qDebug() << FONT_NAME << "is already installed.";
        return true;
    }
    
    // 检查管理员权限
    if (!isAdminPrivileges()) {
        qWarning() << "Administrator privileges required to install font.";
        return false;
    }
    
    // 获取字体源文件路径
    QString appDir = QCoreApplication::applicationDirPath();
    QString sourcePath = appDir + "/fonts/" + FONT_FILE;
    
    // 复制字体到系统目录
    if (!copyFontToSystem(sourcePath)) {
        return false;
    }
    
    // 注册字体到系统
    if (!registerFontInRegistry(FONT_FILE)) {
        qWarning() << "Failed to register font in registry.";
        return false;
    }
    
    qDebug() << FONT_NAME << "installed successfully.";
    return true;
}
2.3 创建启动器程序

cpp

// launcher.cpp - 单独的启动器程序
#include <QApplication>
#include <QMessageBox>
#include <QProcess>
#include <QDir>
#include "fontinstaller.h"

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    
    // 检查思源黑体是否已安装
    if (!FontInstaller::isSourceHanSansInstalled()) {
        QMessageBox msgBox;
        msgBox.setWindowTitle("字体安装");
        msgBox.setText("检测到系统未安装思源黑体,是否立即安装?");
        msgBox.setInformativeText("安装需要管理员权限。");
        msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
        msgBox.setDefaultButton(QMessageBox::Yes);
        
        if (msgBox.exec() == QMessageBox::Yes) {
            // 尝试安装字体
            if (FontInstaller::installSourceHanSans()) {
                QMessageBox::information(nullptr, "成功", "思源黑体安装成功!");
            } else {
                QMessageBox::warning(nullptr, "失败", 
                    "字体安装失败!
"
                    "可能的原因:
"
                    "1. 没有管理员权限
"
                    "2. 字体文件不存在
"
                    "3. 系统限制");
                return 1;
            }
        } else {
            return 1;
        }
    }
    
    // 启动主程序
    QString appPath = QCoreApplication::applicationDirPath() + "/YourQtApp.exe";
    if (QFile::exists(appPath)) {
        QProcess::startDetached(appPath);
    } else {
        QMessageBox::critical(nullptr, "错误", "主程序未找到:" + appPath);
        return 1;
    }
    
    return 0;
}

方案 3:使用 PowerShell 脚本(推荐用于平板)

完整的 PowerShell 字体安装脚本
1. 主安装脚本 
install_fonts.ps1(utf-8格式,防止乱码)

powershell

# install_fonts.ps1 - 思源黑体字体安装脚本
param(
    [string]$FontsDir = "fonts",
    [switch]$Force = $false,
    [switch]$Silent = $false
)

# 脚本信息
$ScriptVersion = "1.0"
$ScriptName = "思源黑体安装脚本"

# 字体文件配置
$FontConfigs = @(
    @{
        FileName = "SourceHanSansSC-Light.otf"
        FontName = "Source Han Sans SC Light"
        RegistryName = "Source Han Sans SC Light (OpenType)"
    },
    @{
        FileName = "SourceHanSansSC-Regular.otf"
        FontName = "Source Han Sans SC"
        RegistryName = "Source Han Sans SC (OpenType)"
    },
    @{
        FileName = "SourceHanSansSC-Medium.otf"
        FontName = "Source Han Sans SC Medium"
        RegistryName = "Source Han Sans SC Medium (OpenType)"
    },
    @{
        FileName = "SourceHanSansSC-Bold.otf"
        FontName = "Source Han Sans SC Bold"
        RegistryName = "Source Han Sans SC Bold (OpenType)"
    },
    @{
        FileName = "SourceHanSansSC-Heavy.otf"
        FontName = "Source Han Sans SC Heavy"
        RegistryName = "Source Han Sans SC Heavy (OpenType)"
    }
)

# 颜色定义
$ColorRed = "Red"
$ColorGreen = "Green"
$ColorYellow = "Yellow"
$ColorCyan = "Cyan"

# 日志函数
function Write-Log {
    param([string]$Message, [string]$Color = "White")
    $Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
    Write-Host "[$Timestamp] $Message" -ForegroundColor $Color
}

function Write-Success {
    param([string]$Message)
    Write-Log "✓ $Message" $ColorGreen
}

function Write-Warning {
    param([string]$Message)
    Write-Log "⚠ $Message" $ColorYellow
}

function Write-Error {
    param([string]$Message)
    Write-Log "✗ $Message" $ColorRed
}

function Write-Info {
    param([string]$Message)
    Write-Log "ℹ $Message" $ColorCyan
}

# 检查管理员权限
function Test-Administrator {
    $currentPrincipal = New-Object Security.Principal.WindowsPrincipal([Security.Principal.WindowsIdentity]::GetCurrent())
    return $currentPrincipal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
}

# 检查字体是否已安装
function Test-FontInstalled {
    param([string]$FontName)
    
    try {
        $installedFonts = Get-ChildItem "HKLM:SOFTWAREMicrosoftWindows NTCurrentVersionFonts"
        foreach ($font in $installedFonts) {
            if ($font.GetValue("") -like "*$FontName*") {
                return $true
            }
        }
        return $false
    }
    catch {
        return $false
    }
}

# 安装单个字体
function Install-Font {
    param(
        [hashtable]$FontConfig,
        [string]$FontsDir
    )
    
    $fileName = $FontConfig.FileName
    $fontName = $FontConfig.FontName
    $registryName = $FontConfig.RegistryName
    
    Write-Info "处理字体: $fontName"
    
    # 检查源文件
    $sourcePath = Join-Path $FontsDir $fileName
    if (-not (Test-Path $sourcePath)) {
        Write-Error "字体文件未找到: $sourcePath"
        return $false
    }
    
    # 检查是否已安装
    if ((-not $Force) -and (Test-FontInstalled $fontName)) {
        Write-Success "字体已安装: $fontName"
        return $true
    }
    
    # 目标路径
    $destPath = Join-Path $env:WINDIR "Fonts$fileName"
    
    try {
        # 复制字体文件
        Write-Info "复制字体文件到系统目录..."
        Copy-Item $sourcePath $destPath -Force
        Write-Success "字体文件复制成功: $fileName"
        
        # 注册字体
        Write-Info "注册字体到系统..."
        $regPath = "HKLM:SOFTWAREMicrosoftWindows NTCurrentVersionFonts"
        New-ItemProperty -Path $regPath -Name $registryName -Value $fileName -PropertyType String -Force | Out-Null
        Write-Success "字体注册成功: $fontName"
        
        # 验证安装
        if (Test-FontInstalled $fontName) {
            Write-Success "字体安装验证成功: $fontName"
            return $true
        } else {
            Write-Warning "字体安装但验证失败: $fontName"
            return $false
        }
    }
    catch {
        Write-Error "安装字体失败: $fontName - $($_.Exception.Message)"
        return $false
    }
}

# 刷新字体缓存
function Update-FontCache {
    Write-Info "刷新系统字体缓存..."
    try {
        # 方法1: 使用 Windows API
        Add-Type -Name FontCache -Namespace Win32 -MemberDefinition @"
[DllImport("gdi32.dll")]
public static extern int AddFontResource(string lpszFilename);
"@
        
        # 方法2: 发送 WM_FONTCHANGE 消息
        $null = [Win32.FontCache]::AddFontResource("$env:WINDIRFonts")
        
        # 广播字体变化
        $Source = @"
using System;
using System.Runtime.InteropServices;
public class FontBroadcast {
    [DllImport("user32.dll")]
    public static extern int SendMessage(int hWnd, uint Msg, int wParam, int lParam);
    
    public static void BroadcastFontChange() {
        const int HWND_BROADCAST = 0xffff;
        const int WM_FONTCHANGE = 0x001D;
        SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0);
    }
}
"@
        Add-Type -TypeDefinition $Source
        [FontBroadcast]::BroadcastFontChange()
        
        Write-Success "字体缓存刷新完成"
        return $true
    }
    catch {
        Write-Warning "字体缓存刷新失败,可能需要重启应用程序: $($_.Exception.Message)"
        return $false
    }
}

# 显示安装摘要
function Show-InstallationSummary {
    param(
        [array]$Results
    )
    
    Write-Host "`n" + "="*50 -ForegroundColor Cyan
    Write-Host "字体安装摘要" -ForegroundColor Cyan
    Write-Host "="*50 -ForegroundColor Cyan
    
    $successCount = ($Results | Where-Object { $_ -eq $true }).Count
    $totalCount = $Results.Count
    
    foreach ($result in $Results) {
        $fontConfig = $FontConfigs[$Results.IndexOf($result)]
        $status = if ($result) { "✓ 成功" } else { "✗ 失败" }
        $color = if ($result) { $ColorGreen } else { $ColorRed }
        Write-Host "  $($fontConfig.FontName): $status" -ForegroundColor $color
    }
    
    Write-Host "`n总计: $successCount/$totalCount 个字体安装成功" -ForegroundColor Cyan
    
    if ($successCount -eq $totalCount) {
        Write-Success "所有字体安装完成!"
    } elseif ($successCount -gt 0) {
        Write-Warning "部分字体安装完成,请检查失败的字体。"
    } else {
        Write-Error "所有字体安装失败!"
    }
}

# 主安装函数
function Start-FontInstallation {
    Write-Host "`n" + "="*60 -ForegroundColor Yellow
    Write-Host $ScriptName -ForegroundColor Yellow
    Write-Host "版本: $ScriptVersion" -ForegroundColor Yellow
    Write-Host "="*60 -ForegroundColor Yellow
    
    # 检查管理员权限
    if (-not (Test-Administrator)) {
        Write-Error "需要管理员权限来安装字体。"
        Write-Host "请右键点击 PowerShell 并选择'以管理员身份运行'" -ForegroundColor Red
        return 1
    }
    
    Write-Success "管理员权限验证通过"
    
    # 检查字体目录
    if (-not (Test-Path $FontsDir)) {
        Write-Error "字体目录不存在: $FontsDir"
        return 1
    }
    
    Write-Success "字体目录找到: $FontsDir"
    
    # 安装字体
    $installationResults = @()
    
    foreach ($fontConfig in $FontConfigs) {
        $result = Install-Font -FontConfig $fontConfig -FontsDir $FontsDir
        $installationResults += $result
        Start-Sleep -Milliseconds 100  # 短暂延迟
    }
    
    # 刷新字体缓存
    Update-FontCache
    
    # 显示摘要
    Show-InstallationSummary -Results $installationResults
    
    # 启动 Qt 应用程序(如果存在)
    $qtAppPath = "YourQtApp.exe"
    if (Test-Path $qtAppPath) {
        Write-Info "启动 Qt 应用程序..."
        Start-Process -FilePath $qtAppPath
        Write-Success "应用程序已启动"
    }
    
    return 0
}

# 脚本入口点
try {
    $exitCode = Start-FontInstallation
    exit $exitCode
}
catch {
    Write-Error "脚本执行失败: $($_.Exception.Message)"
    Write-Host "完整错误信息:" -ForegroundColor Red
    Write-Host $_.Exception.StackTrace -ForegroundColor Red
    exit 1
}
2. 批处理启动文件 
install_fonts.bat

batch

@echo off
REM install_fonts.bat - 字体安装启动器
chcp 65001 >nul
title 思源黑体安装程序

echo ================================
echo     思源黑体字体安装程序
echo ================================
echo.

REM 检查 PowerShell 版本
powershell -Command "if ($PSVersionTable.PSVersion.Major -lt 3) { exit 1 }"
if errorlevel 1 (
    echo错误: 需要 PowerShell 3.0 或更高版本
    pause
    exit /b 1
)

REM 以管理员权限运行 PowerShell 脚本
powershell -ExecutionPolicy Bypass -File "install_fonts.ps1" %*

if errorlevel 1 (
    echo.
    echo字体安装过程中出现错误。
    pause
) else (
    echo.
    echo字体安装完成!
    timeout /t 3 >nul
)
3. 配置文件 
font_config.json
(可选)

json

{
  "font_packages": [
    {
      "name": "思源黑体简体中文",
      "version": "2.004",
      "fonts": [
        {
          "file": "SourceHanSansSC-Light.otf",
          "name": "Source Han Sans SC Light",
          "registry": "Source Han Sans SC Light (OpenType)"
        },
        {
          "file": "SourceHanSansSC-Regular.otf",
          "name": "Source Han Sans SC",
          "registry": "Source Han Sans SC (OpenType)"
        },
        {
          "file": "SourceHanSansSC-Medium.otf", 
          "name": "Source Han Sans SC Medium",
          "registry": "Source Han Sans SC Medium (OpenType)"
        },
        {
          "file": "SourceHanSansSC-Bold.otf",
          "name": "Source Han Sans SC Bold", 
          "registry": "Source Han Sans SC Bold (OpenType)"
        },
        {
          "file": "SourceHanSansSC-Heavy.otf",
          "name": "Source Han Sans SC Heavy",
          "registry": "Source Han Sans SC Heavy (OpenType)"
        }
      ]
    }
  ]
}
4. 项目目录结构

text

应用程序目录/
├── fonts/
│   ├── SourceHanSansSC-Light.otf
│   ├── SourceHanSansSC-Regular.otf
│   ├── SourceHanSansSC-Medium.otf
│   ├── SourceHanSansSC-Bold.otf
│   └── SourceHanSansSC-Heavy.otf
├── install_fonts.ps1
├── install_fonts.bat
├── font_config.json (可选)
└── YourQtApp.exe
使用说明
基本使用:

batch

# 双击运行
install_fonts.bat

# 或者直接运行 PowerShell
powershell -ExecutionPolicy Bypass -File install_fonts.ps1
高级选项:

batch

# 强制重新安装所有字体
install_fonts.bat -Force

# 静默模式(无交互)
install_fonts.bat -Silent

# 指定自定义字体目录
install_fonts.bat -FontsDir "C:MyFonts"

方法二(不安装字体到系统font目录下)

将字体库加载到qt中的资源文件中,通过字体管理类(FontManager)管理该字体。在界面相关代码中对每个控件设置新字体。

字体管理类

1. 头文件 (fontmanager.h)

cpp

#ifndef FONTMANAGER_H
#define FONTMANAGER_H

#include <QString>
#include <QFont>
#include <QMap>

class FontManager
{
public:
    // 精确的字重枚举,对应您拥有的文件
    enum FontWeight {
        Light,      // SourceHanSansSC-Light.otf
        Regular,    // SourceHanSansSC-Regular.otf  
        Bold,       // SourceHanSansSC-Bold.otf
        Heavy       // SourceHanSansSC-Heavy.otf
    };

    // 初始化字体系统
    static void initialize();
    
    // 获取字体
    static QFont getFont(FontWeight weight = Regular, int pointSize = 10);
    static QFont getFont(const QString &weightName, int pointSize = 10);
    
    // 工具函数
    static QString getFontFamily(FontWeight weight = Regular);
    static bool isFontLoaded(FontWeight weight);
    static QString getWeightName(FontWeight weight);
    
    // 预定义字体样式
    static QFont light(int pointSize = 10);
    static QFont regular(int pointSize = 10);
    static QFont bold(int pointSize = 10);
    static QFont heavy(int pointSize = 10);

private:
    static bool loadSpecificFonts();
    static QMap<FontWeight, QString> m_fontFamilies;
    static bool m_initialized;
    
    // 字体文件路径映射
    static QMap<FontWeight, QString> getFontFileMap();
};

#endif // FONTMANAGER_H

2. 实现文件 (fontmanager.cpp)

cpp

#include "fontmanager.h"
#include <QFontDatabase>
#include <QDebug>
#include <QFile>

QMap<FontManager::FontWeight, QString> FontManager::m_fontFamilies;
bool FontManager::m_initialized = false;

void FontManager::initialize()
{
    if (m_initialized) {
        qDebug() << "FontManager already initialized";
        return;
    }
    
    if (loadSpecificFonts()) {
        qDebug() << "FontManager initialized successfully";
        m_initialized = true;
        
        // 打印加载的字体信息
        for (auto it = m_fontFamilies.begin(); it != m_fontFamilies.end(); ++it) {
            qDebug() << "Loaded:" << getWeightName(it.key()) << "->" << it.value();
        }
    } else {
        qWarning() << "FontManager initialization failed";
        m_initialized = true; // 标记为已初始化,但使用回退字体
    }
}

QMap<FontManager::FontWeight, QString> FontManager::getFontFileMap()
{
    // 精确映射您拥有的字体文件
    return {
        {Light,    ":/fonts/SourceHanSansSC-Light.otf"},
        {Regular,  ":/fonts/SourceHanSansSC-Regular.otf"},
        {Bold,     ":/fonts/SourceHanSansSC-Bold.otf"},
        {Heavy,    ":/fonts/SourceHanSansSC-Heavy.otf"}
    };
}

bool FontManager::loadSpecificFonts()
{
    auto fontFiles = getFontFileMap();
    bool allSuccess = true;
    
    for (auto it = fontFiles.begin(); it != fontFiles.end(); ++it) {
        FontWeight weight = it.key();
        QString filePath = it.value();
        
        // 检查文件是否存在
        if (!QFile::exists(filePath)) {
            qWarning() << "Font file not found:" << filePath;
            allSuccess = false;
            continue;
        }
        
        // 加载字体
        int fontId = QFontDatabase::addApplicationFont(filePath);
        if (fontId == -1) {
            qWarning() << "Failed to load font:" << filePath;
            allSuccess = false;
            continue;
        }
        
        // 获取字体家族名
        QStringList families = QFontDatabase::applicationFontFamilies(fontId);
        if (families.isEmpty()) {
            qWarning() << "No font families found in:" << filePath;
            allSuccess = false;
            continue;
        }
        
        m_fontFamilies[weight] = families.first();
        qDebug() << "Successfully loaded" << getWeightName(weight) << "from" << filePath;
    }
    
    return !m_fontFamilies.isEmpty();
}

QFont FontManager::getFont(FontWeight weight, int pointSize)
{
    if (!m_initialized) {
        initialize();
    }
    
    // 如果有对应的字体文件,直接使用
    if (m_fontFamilies.contains(weight)) {
        QFont font(m_fontFamilies[weight]);
        font.setPointSize(pointSize);
        return font;
    }
    
    // 回退方案:使用 Regular 字重
    qWarning() << "Font weight not available, falling back to Regular:" << getWeightName(weight);
    if (m_fontFamilies.contains(Regular)) {
        QFont font(m_fontFamilies[Regular]);
        font.setPointSize(pointSize);
        
        // 尝试设置相应的 Qt 权重
        switch (weight) {
        case Light: font.setWeight(QFont::Light); break;
        case Bold: font.setWeight(QFont::Bold); break;
        case Heavy: 
            font.setWeight(QFont::Black);
            font.setBold(true);
            break;
        default: break;
        }
        
        return font;
    }
    
    // 终极回退:系统字体
    qCritical() << "No fonts available, using system font";
    return QFont("Microsoft YaHei", pointSize);
}

QFont FontManager::getFont(const QString &weightName, int pointSize)
{
    static QMap<QString, FontWeight> weightMap = {
        {"light", Light},
        {"regular", Regular},
        {"normal", Regular},
        {"bold", Bold},
        {"heavy", Heavy},
        {"black", Heavy},
        {"extrabold", Heavy}
    };
    
    QString key = weightName.toLower().trimmed();
    FontWeight weight = weightMap.value(key, Regular);
    
    return getFont(weight, pointSize);
}

QString FontManager::getFontFamily(FontWeight weight)
{
    if (!m_initialized) {
        initialize();
    }
    
    if (m_fontFamilies.contains(weight)) {
        return m_fontFamilies[weight];
    }
    
    if (m_fontFamilies.contains(Regular)) {
        return m_fontFamilies[Regular];
    }
    
    return "Microsoft YaHei"; // 最终回退
}

bool FontManager::isFontLoaded(FontWeight weight)
{
    return m_initialized && m_fontFamilies.contains(weight);
}

QString FontManager::getWeightName(FontWeight weight)
{
    static QMap<FontWeight, QString> names = {
        {Light, "Light"},
        {Regular, "Regular"},
        {Bold, "Bold"},
        {Heavy, "Heavy"}
    };
    return names.value(weight, "Unknown");
}

// 预定义字体样式的便捷函数
QFont FontManager::light(int pointSize)
{
    return getFont(Light, pointSize);
}

QFont FontManager::regular(int pointSize)
{
    return getFont(Regular, pointSize);
}

QFont FontManager::bold(int pointSize)
{
    return getFont(Bold, pointSize);
}

QFont FontManager::heavy(int pointSize)
{
    return getFont(Heavy, pointSize);
}

3. 资源文件配置 (resources.qrc)

xml

<RCC>
    <qresource prefix="/fonts">
        <file>fonts/SourceHanSansSC-Light.otf</file>
        <file>fonts/SourceHanSansSC-Regular.otf</file>
        <file>fonts/SourceHanSansSC-Bold.otf</file>
        <file>fonts/SourceHanSansSC-Heavy.otf</file>
    </qresource>
</RCC>

4. 使用示例

cpp

// 在各种页面中的使用示例
void MainWindow::setupFonts()
{
    // 方法1: 使用枚举
    ui->labelTitle->setFont(FontManager::getFont(FontManager::Heavy, 24));
    ui->labelSubtitle->setFont(FontManager::getFont(FontManager::Bold, 18));
    ui->labelContent->setFont(FontManager::getFont(FontManager::Regular, 14));
    ui->labelHint->setFont(FontManager::getFont(FontManager::Light, 12));
    
    // 方法2: 使用字符串(更灵活)
    ui->buttonPrimary->setFont(FontManager::getFont("heavy", 16));
    ui->buttonSecondary->setFont(FontManager::getFont("bold", 14));
    
    // 方法3: 使用便捷函数
    ui->statusLabel->setFont(FontManager::light(11));
    ui->footerLabel->setFont(FontManager::regular(12));
}

void SettingsPage::setupFonts()
{
    // 您的历史系数标签 - 使用真正的 Heavy 字重
    ui->labelHistoryCoefficientName->setFont(FontManager::heavy(32));
    ui->labelHistoryCoefficientValue->setFont(FontManager::heavy(32));
    
    // 验证字体加载
    if (FontManager::isFontLoaded(FontManager::Heavy)) {
        qDebug() << "Heavy 字重已正确加载";
        qDebug() << "字体家族:" << FontManager::getFontFamily(FontManager::Heavy);
    } else {
        qWarning() << "Heavy 字重加载失败,使用回退方案";
    }
}
© 版权声明

相关文章

暂无评论

none
暂无评论...