如何在Tkinter中使用freetype-py显示一个字母?

编程语言 2026-07-11

我想在Tkinter中微调某些文本元素,偶然发现了 freetype-py。我不知道该如何实现它。

如何显示 freetype-py 的一个字母?我之前的所有尝试都以错误告终。

尝试1

import tkinter as tk
import freetype as ft

face = ft.Face("C:/Windows/Fonts/arial.ttf")
face.set_char_size(12*64)
char = 'x'
face.load_char(char, ft.FT_LOAD_RENDER)
bmp = face.glyph.bitmap

root = tk.Tk()
img = tk.BitmapImage(data=bmp)
canvas = tk.Canvas(root)
cid = canvas.create_bitmap(0, 0)
canvas.itemconfigure(cid, bitmap=img)
canvas.pack()
root.mainloop()

失败原因:

_tkinter.TclError: format error in bitmap data

尝试2

img = Image.frombytes('L', (bmp.width, bmp.rows), bytes(bmp.buffer))
img = ImageTk.BitmapImage(img)

失败原因:

ValueError: not a bitmap

尝试3

img = Image.frombytes('L', (bmp.width, bmp.rows), bytes(bmp.buffer))
img = ImageTk.PhotoImage(img)
cid = canvas.create_image(20, 20)
canvas.itemconfigure(cid, image=img)

结果是黑色背景,白色前景。

解决方案

使用freetype-py与 Tkinter集成确实存在一些问题。 首先,你可能会想使用一个 BitmapImage,但 face.glyph.bitmap 未必是符合 预期的X11 .bpm 格式 的类型(至少在Win32下它不起作用)。

然后你可能会考虑使用 PIL 来转换数据,但Tkinter仍会抱怨你的数据不是位图。 之后,你可能会尝试切换到一个 PhotoImage,但现在你没有任何 -background 选项,所以你的图像会显示为黑色背景。

为省去这些挫折,你可以从下面的代码开始。

import tkinter as tk
from PIL import Image, ImageOps, ImageTk
import freetype as ft

face = ft.Face("C:/Windows/Fonts/arial.ttf")
face.set_char_size(12*64) # size*64 bits

def write(event):
    char = event.char
    if char:
        face.load_char(char, ft.FT_LOAD_RENDER)
        bmp = face.glyph.bitmap

        # Create an image from bytes
        img = Image.frombytes('L', (bmp.width, bmp.rows), bytes(bmp.buffer))
        img = ImageOps.invert(img)

        # Convert to RGBA to avoid a black background
        img = img.convert("RGBA")

        # Finally, convert to a Tkinter PhotoImage
        img = ImageTk.PhotoImage(img)

        # Keep a reference to the image
        canvas._img = img

        # Display the image in your Canvas
        canvas.itemconfigure(cid, image=img)
    return

root = tk.Tk()
canvas = tk.Canvas(root)
cid = canvas.create_image(20, 20)
canvas.pack()
root.bind('<Key>', write)
root.mainloop()
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章