本文介绍如何在不重启应用的前提下,实时更新 Kivy 中所有 Label 小部件的字体属性,通过递归遍历 widget 树并手动同步 default_font 配置值实现全局字体切换。
本文介绍如何在不重启应用的前提下,实时更新 kivy 中所有 label 小部件的字体属性,通过递归遍历 widget 树并手动同步 `default_font` 配置值实现全局字体切换。
在 Kivy 中,Config.set('kivy', 'default_font', ...) 仅影响新创建的 Label 实例,并不会自动刷新已存在的 widget 字体。因此,即使你成功修改了配置并调用 Config.write() 持久化,界面上已渲染的 Label 仍保持旧字体。要实现真正的“运行时全局字体切换”,必须主动遍历当前 UI 树,定位所有 Label(及可能继承自它的自定义文本控件),并显式更新其 font_name 属性。
以下是一个健壮、可复用的递归更新方案:
from kivy.app import App
from kivy.config import Config
from kivy.uix.label import Label
from kivy.uix.widget import Widget
def update_font_recursive(widget):
"""递归更新 widget 树中所有 Label 的 font_name 属性"""
# 检查当前 widget 是否为 Label(或其子类)
if isinstance(widget, Label):
# 从 Config 读取最新 default_font 列表,取第一个元素作为字体文件路径
font_config = Config.get('kivy', 'default_font')
if isinstance(font_config, list) and len(font_config) > 0:
widget.font_name = font_config[0]
# 若 widget 具有 children 属性(如 Layout、Screen、BoxWidget 等),继续递归
if hasattr(widget, 'children') and widget.children:
for child in widget.children:
update_font_recursive(child)
该函数应于字体选择后立即调用,作用于整个应用的根节点(即 App.get_running_app().root):
class SettingsScreen(Screen):
def on_font_selected(self, font_filename, font_filepath):
# 更新 Kivy 全局配置
Config.set('kivy', 'default_font', [
font_filename,
font_filepath, # regular
font_filepath, # bold
font_filepath, # italic
font_filepath # bold+italic
])
Config.write() # 写入配置文件,确保下次启动生效
# 关键步骤:立即刷新所有现存 Label
app = App.get_running_app()
if app and app.root:
update_font_recursive(app.root)
⚠️ 注意事项:
- Config.get('kivy', 'default_font') 返回的是一个包含 5 个路径的列表(对应 normal/bold/italic/bold_italic/fallback),务必取 [0] 获取主字体;
- 此方法不自动处理动态添加的 widget(如后续 add_widget() 新增的 Label),建议在创建新 Label 时统一设置 font_name,或封装一个工厂函数;
- 若使用 TextInput、Button(含文本)、ToggleButton 等含文本属性的控件,需扩展 update_font_recursive 以覆盖 font_name 可写属性(例如 isinstance(widget, (Label, Button, TextInput)));
- 对于复杂嵌套(如 ScrollView 内部内容未加载完成),请确保在 widget 已完成构建且 children 非空后再执行更新;
- 若项目采用 kv 语言定义界面,确保 .kv 文件中未硬编码 font_name,否则会覆盖运行时设置。
综上,Kivy 并未提供开箱即用的“热重载默认字体”机制,但借助轻量级递归遍历与显式赋值,即可高效、可靠地实现用户期望的实时字体切换体验。










