Tkinter 中真正自定义的字体

2025-04-10 09:45:00
admin
原创
17
摘要:问题描述:我正在 Tkinter 中制作一个界面,我需要自定义字体。不仅仅是特定大小的 Helvetica 字体,还包括特定平台上通常可用的字体以外的字体。这些字体将作为图像文件或(最好)Truetype 字体文件或类似文件与程序一起保存。我不想在每台要使用该程序的机器上安装所需的字体,我只想将它们与程序一起...

问题描述:

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

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


解决方案 1:

有一种方法可以将外部字体放入 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 中查找并硬编码到应用程序中,这可能更容易。编辑tkFont.families():或者,根据下面 patthoyt 的评论,在(作为最后一项,或者更可靠地,通过比较加载字体之前和之后的系列列表)中查找它。

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

有兴趣的可以看看几年前在 [TCLCORE] 上关于这个话题的讨论。更多背景信息:MSDN 上的字体

解决方案 2:

如果不借助特定于平台的 hack,就无法将外部字体文件加载到 Tkinter 中。Tkinter 中没有内置任何支持此功能的东西。

解决方案 3:

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

解决方案 4:

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

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

解决方案 5:

tkextrafont在我看来是最轻量和最简单的,在 PyPI 上为 Windows 和 Linux 预建了轮子。例如:

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

解决方案 6:

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

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

解决方案 7:

对于 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))

解决方案 8:

对于将来遇到此问题的人来说,他们想要一个非常简单的解决方案和跨平台实现。这个答案可能是 2012 年 8 月 16 日无效链接中讨论的答案。您可以使用 PILImageFont.truetype()来渲染字体,然后使用Image.new()ImageDraw.Draw。我把它放到了一个类中。

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
相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2482  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1533  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   0  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   0  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用