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中查找名称并将其硬编码到应用程序中。edit:或者,根据patthoyt下面的评论,在tkFont.families()中查找它(作为最后一项,或者,更可靠地,通过比较加载字体前后的系列列表)。 我在digsby(license)中找到了这个函数;这里定义了一个unloadfont函数,如果你想在程序执行完之前删除字体的话(你也可以只依赖private设置在程序结束时卸载字体)。 对于感兴趣的人,here是几年前在[TCLCORE]上对这个主题的讨论。fonts on MSDN
import tkinter as tk
from tkextrafont import Font
window = tk.Tk()
font = Font(file="tests/overhaul.ttf", family="Overhaul")
tk.Label(window, text="Hello", font=font).pack()
window.mainloop()
class RenderFont:
def __init__(self, filename, fill=(0, 0, 0):
"""
constructor for RenderFont
filename: the filename to the ttf font file
fill: the color of the text
"""
self._file = filename
self._fill = fill
self._image = None
def get_render(self, font_size, txt, type_="normal"):
"""
returns a transparent PIL image that contains the text
font_size: the size of text
txt: the actual text
type_: the type of the text, "normal" or "bold"
"""
if type(txt) is not str:
raise TypeError("text must be a string")
if type(font_size) is not int:
raise TypeError("font_size must be a int")
width = len(txt)*font_size
height = font_size+5
font = ImageFont.truetype(font=self._file, size=font_size)
self._image = Image.new(mode='RGBA', size=(width, height), color=(255, 255, 255))
rgba_data = self._image.getdata()
newdata = []
for item in rgba_data:
if item[0] == 255 and item[1] == 255 and item[2] == 255:
newdata.append((255, 255, 255, 0))
else:
newdata.append(item)
self._image.putdata(newdata)
draw = ImageDraw.Draw(im=self._image)
if type_ == "normal":
draw.text(xy=(width/2, height/2), text=txt, font=font, fill=self._fill, anchor='mm')
elif type_ == "bold":
draw.text(xy=(width/2, height/2), text=txt, font=font, fill=self._fill, anchor='mm',
stroke_width=1, stroke_fill=self._fill)
return self._image
8条答案
按热度按时间nwsw7zdq1#
有一种方法可以将外部字体导入Windows上的Tkinter。
实现此功能的关键代码是以下函数:
在使用字体文件的路径调用
loadfont
之后(其可以是.fon
、.fnt
、.ttf
、.ttc
、.fot
、.otf
、.mmm
、.pfb
或.pfm
中的任一个),你可以加载字体像任何其他安装字体tkFont.Font(family=XXX, ...)
.和使用它在任何地方你喜欢. [见MSDN为更多信息]这里最大的警告是字体的族名称不一定是文件的名称;它嵌入在字体数据中。与其试图解析出名称,不如在字体浏览器GUI中查找名称并将其硬编码到应用程序中。edit:或者,根据patthoyt下面的评论,在
tkFont.families()
中查找它(作为最后一项,或者,更可靠地,通过比较加载字体前后的系列列表)。我在digsby(license)中找到了这个函数;这里定义了一个
unloadfont
函数,如果你想在程序执行完之前删除字体的话(你也可以只依赖private
设置在程序结束时卸载字体)。对于感兴趣的人,here是几年前在[TCLCORE]上对这个主题的讨论。fonts on MSDN
mitkmikd2#
这对我在windows上工作,但似乎不工作在linux上:
sy5wg1nm3#
不借助特定于平台的技巧是无法将外部字体文件加载到Tkinter中的,Tkinter没有内置的东西来支持它。
vxf3dgd44#
我找到了this discussion,他们在那里介绍了如何使用一行文本作为图像,并使用PIL将其放置到窗口中。这可能是一个解决方案。
我找不到使用tkFont在tkFont man page中导入捆绑字体的方法。
cotxawn75#
tkextrafont在我看来是最轻量级和最简单的,在PyPI上为Windows和Linux预先构建了轮子。
ehxuflar6#
对我来说,这是一个简单的解决方案:
lrl1mhuk7#
对于Linux,我可以将
otf
字体文件安装到系统字体目录中:我发现这个主目录可以工作,最后改用它:
在任何一种情况下,我都可以使用一个字符串font-name来加载它(正如所有tkinter文档所示):
hvvq6cgz8#
对于将来遇到这个问题的人,他们需要一个非常简单的解决方案和跨平台的实现。这个答案可能是2012年8月16日无效链接中讨论的答案。你可以使用PIL的
ImageFont.truetype()
来渲染字体,然后使用Image.new()
和ImageDraw.Draw
。我已经把它放在一个类中。