python - Tkinter 中真正的自定义字体

标签 python fonts tkinter

我在 Tkinter 中制作界面,我需要自定义字体。不仅仅是,比如说,特定大小的 Helvetica 字体,而是任何给定平台上通常可用的字体以外的字体。这将作为图像文件或(最好)Truetype 字体文件或类似文件与程序一起保存。我不想在每台要使用该程序的机器上都安装所需的字体,我只想将它们与程序放在同一目录中。

tkFont 模块看起来应该做这样的事情,但我看不出它会在哪里为运行该程序的系统通常无法访问的字体获取文件名。 预先感谢您的帮助。

最佳答案

有一种方法可以将外部字体导入 Windows 上的 Tkinter。

完成这项工作的关键代码是以下函数:

from ctypes import windll, byref, create_unicode_buffer, create_string_buffer
FR_PRIVATE  = 0x10
FR_NOT_ENUM = 0x20

def loadfont(fontpath, private=True, enumerable=False):
    '''
    Makes fonts located in file `fontpath` available to the font system.

    `private`     if True, other processes cannot see this font, and this 
                  font will be unloaded when the process dies
    `enumerable`  if True, this font will appear when enumerating fonts

    See https://msdn.microsoft.com/en-us/library/dd183327(VS.85).aspx

    '''
    # This function was taken from
    # https://github.com/ifwe/digsby/blob/f5fe00244744aa131e07f09348d10563f3d8fa99/digsby/src/gui/native/win/winfonts.py#L15
    # This function is written for Python 2.x. For 3.x, you
    # have to convert the isinstance checks to bytes and str
    if isinstance(fontpath, str):
        pathbuf = create_string_buffer(fontpath)
        AddFontResourceEx = windll.gdi32.AddFontResourceExA
    elif isinstance(fontpath, unicode):
        pathbuf = create_unicode_buffer(fontpath)
        AddFontResourceEx = windll.gdi32.AddFontResourceExW
    else:
        raise TypeError('fontpath must be of type str or unicode')

    flags = (FR_PRIVATE if private else 0) | (FR_NOT_ENUM if not enumerable else 0)
    numFontsAdded = AddFontResourceEx(byref(pathbuf), flags, 0)
    return bool(numFontsAdded)

使用字体文件的路径调用 loadfont 后(可以是 .fon.fnt 中的任何一个) .ttf, .ttc, .fot, .otf, .mmm, .pfb.pfm),您可以像加载任何其他已安装的字体一样加载字体 tkFont.Font(family=XXX, ...)。并在任何你喜欢的地方使用它。 [参见MSDN获取更多信息]

这里最大的警告是字体的姓氏不一定是文件名;它嵌入在字体数据中。与其尝试解析名称,不如在字体浏览器 GUI 中查找它并将其硬编码到您的应用程序中可能会更容易。 编辑:或者,根据下面 patthoyt 的评论,在 tkFont.families() 中查找(作为最后一项,或者更稳健地,通过比较之前的家族列表加载字体后)。

我在 digsby 中找到了这个函数( license );如果你想在程序完成执行之前删除字体,这里定义了一个 unloadfont 函数。 (您也可以仅依靠 private 设置在程序结束时卸载字体。)

任何有兴趣的人,here是几年前在【TCLCORE】上关于这个话题的讨论。更多背景:fonts on MSDN

关于python - Tkinter 中真正的自定义字体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11993290/

相关文章:

python - 将文件头解析为 Python/pandas 中的日期对象

javascript - 为什么这个 ejs 变量的 fontFamily 未定义?

WPF - 添加自定义字体

java - 为什么我的Font是从文件创建的,为什么还要调用GraphicsEnvorinment.registerFont()?

python - 如何删除复选框小部件 tkinter 周围的浅灰色?

python - 如何使 tkinter 窗口在 i3 窗口管理器中 float

fonts - Mac OS X 上的 Tkinter 字体

python - Python for循环中发生的内部操作

python - 如何使用字符串引用类的实例?

python - 记录抽象基类的属性?