一、思源黑体
思源黑体是一款由 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格式,防止乱码)
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(无管理员权限检查)
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
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格式,防止乱码)
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
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(可选)
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 字重加载失败,使用回退方案";
}
}