真正的自定义字体在Tkinter

Ver*_*iss 14 python fonts tkinter

我在Tkinter中创建一个界面,我需要自定义字体.不仅仅是说,Helvetica只有一定的尺寸或者其他什么,而是除了通常在任何给定平台上可用的字体之外的字体.这将是程序作为图像文件或(优选地)Truetype字体文件或类似文件保存的东西.我不想在将要使用该程序的每台机器上安装所需的字体,我只想在同一目录中随身携带它们.

tkFont模块看起来应该做这样的事情,但是我无法看到运行该程序的系统通常无法访问的字体的文件名.在此先感谢您的帮助.

Fel*_*ipe 9

有一种方法可以将外部字体输入Tkinter [Windows]

(在Windows上,至少)

使这项工作的关键代码是以下功能:

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)
Run Code Online (Sandbox Code Playgroud)

在调用loadfont的路径到您的字体文件(可以是任意的.fon,.fnt,.ttf,.ttc,.fot,.otf,.mmm,.pfb,或.pfm),您可以加载像任何其他已安装的字体的字体tkFont.Font(family=XXX, ...).并在任何你喜欢的地方使用它.[有关详细信息,请参阅MSDN ]

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

我在digsby(许可证)中找到了这个功能; unloadfont如果要在程序完成执行之前删除字体,则会在其中定义一个函数.(您也可以依靠private设置在程序结束时卸载字体.)

对于任何有兴趣的人,这里是几年前关于[TCLCORE]的这个主题的讨论.更多背景:MSDN上的字体

  • 如果您避免传递 FR_NOT_ENUM,则字体名称在“tkinter.font.families()”中可见。当我测试它时,它被附加到列表的末尾,因此看起来 `tkinter.font.families()[-1]` 将是您需要传递给 Tk 的名称。 (2认同)

mat*_*mer 8

这在 Windows 上对我有用,但在 linux 上似乎不起作用:

import pyglet,tkinter
pyglet.font.add_file('file.ttf')

root = tkinter.Tk()
MyLabel = tkinter.Label(root,text="test",font=('font name',25))
MyLabel.pack()
root.mainloop()
Run Code Online (Sandbox Code Playgroud)

  • 也为我工作过。它不安装字体,只是让代码使用该字体。 (2认同)

Bry*_*ley 7

没有办法将外部字体文件加载到Tkinter而不诉诸平台特定的黑客攻击.Tkinter没有任何内置支持它.


Kev*_*don 5

我发现了这个讨论,他们介绍了如何将一行文本用作图像并使用 PIL 将其放入窗口中。那可能是一个解决方案。

我在tkFont 手册页中找不到使用 tkFont 导入捆绑字体的方法

  • 无法再打开讨论链接 (5认同)
  • 你是对的。我也找不到讨论的存档。基本上我现在对它的理解是,您可以使用 PIL 中的自定义字体渲染出文本,然后使用 Tkinter 将其放入窗口中,但是我已经考虑这个问题已经好几年了:) [这是一个使用 PIL 进行图像处理的链接](http://codeidol.com/community/python/viewing-and-processing-images-with-pil/17565/)。 (2认同)