真正的自定义字体在Tkinter

时间:2012-08-16 18:30:37

标签: python fonts tkinter

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

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

6 个答案:

答案 0 :(得分:7)

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

答案 1 :(得分:7)

有一种方法可以将外部字体输入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)

使用您的字体文件的路径loadfont(可以是.fon.fnt.ttf.ttc,{{ 1}},.fot.otf.mmm.pfb),您可以像任何其他已安装的字体.pfm一样加载字体。并在任何你喜欢的地方使用它。 [有关详细信息,请参阅MSDN]

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

我在digsbylicense)中找到了此功能;如果要在程序完成执行之前删除字体,那么在那里定义了tkFont.families()函数。 (您也可以依靠unloadfont设置在程序结束时卸载字体。)

对于任何感兴趣的人,here是几年前关于[TCLCORE]的这个主题的讨论。还有一些背景:fonts on MSDN

答案 2 :(得分:7)

这在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()

答案 3 :(得分:2)

我找到this discussion,其中介绍了如何使用一行文字作为图像,并使用PIL将其放入窗口。这可能是一个解决方案。

我找不到使用tkFont导入tkFont man page中的捆绑字体的方法。

答案 4 :(得分:0)

这对我来说是一个简单的解决方案:

import pyglet, tkinter
pyglet.font.add_file("your font path here")
#then you can use the font as you would normally

答案 5 :(得分:0)

对于Linux,我能够将拥有的otf字体文件安装到系统字体目录中:

mkdir /usr/share/fonts/opentype/my_fonts_name
cp ~/Downloads/my_fonts_name.otf /usr/share/fonts/opentype/my_fonts_name/

我发现此主目录有效,并最终改为使用它:

mkdir ~/.fonts/
cp ~/Downloads/my_fonts_name.otf ~/.fonts/

无论哪种情况,我都可以使用字体名称的字符串加载(如所有tkinter文档所示):

# unshown code
self.canvas = tk.Canvas(self.data_frame, background="black")
self.canvas.create_text(event.x, event.y, text=t, tags='clicks', 
                        fill='firebrick1',
                        font=("My Fonts Name", 22))