如何交替使用tkinter.font.font和PIL.ImageFont.FreeTypeFont?

2024-10-01 00:35:25 发布

您现在位置:Python中文网/ 问答频道 /正文

当使用tkinter.font.FontPIL.ImageFont.FreeTypeFont对象时,我得到了不同的文本测量值(即一行文本的像素宽度)

示例代码(python 3)

import tkinter as tk
from tkinter.font import Font
import shlex, subprocess
import PIL

"""
Get the path of the font to use with PIL 
"""
def get_font_path(fname):
    command_line = str('fc-match -f "%{file}\n" '+fname)
    args = shlex.split(command_line)
    p=subprocess.check_output(args, stderr=subprocess.STDOUT)
    fontpath = p.decode('UTF-8').splitlines()[0]
    print(fontpath)
    return fontpath



fname = 'Courier'
fsize = 14
sampletxt = "Am I a beagle?"

fontpath = get_font_path(fname)
pilfont = PIL.ImageFont.FreeTypeFont(font=fontpath, size=fsize)
print(f'width, height: {pilfont.getsize(sampletxt)}')

上述PIL测量的输出

/usr/share/fonts/type1/texlive-fonts-recommended/pcrr8a.pfb
width, height: (112, 14)

示例代码继续..

"""
The Tkinter measurements
"""

##root = tk.Tk() #Don't need this apparently 
tkfont = Font(family="Courier", size=fsize)
print(f'width, height: {(tkfont.measure(sampletxt), tkfont.metrics("linespace"))}')

tkfont.actual()

上述Tkinter测量的输出:

width, height: (168, 17)

{'family': 'gothic',
 'size': 14,
 'weight': 'normal',
 'slant': 'roman',
 'underline': 0,
 'overstrike': 0}

这些值是不同的。显然,tkinter使用的是不同的字体,但从哪里开始? 使Tkinter使用在PIL对象中指定的相同字体可以解决此问题,但我无法确定tkinter如何加载或使用字体

我已经研究了这个相关的问题,但我使用的是debian(ubuntu)而不是Windows

这里有一些更多的tkinter字体属性,如果它对你有帮助的话

tkinter.font.families() 

## OUTPUT:

('fangsong ti',
 'fixed',
 'clearlyu alternate glyphs',
 'courier 10 pitch',
 'open look glyph',
 'bitstream charter',
 'song ti',
 'open look cursor',
 'newspaper',
 'clearlyu ligature',
 'mincho',
 'clearlyu devangari extra',
 'clearlyu pua',
 'clearlyu',
 'clean',
 'nil',
 'clearlyu arabic',
 'clearlyu devanagari',
 'gothic',
 'clearlyu arabic extra')
tkinter.font.names()

##OUTPUT:

('TkCaptionFont',
 'TkSmallCaptionFont',
 'TkTooltipFont',
 'font308',
 'TkFixedFont',
 'TkHeadingFont',
 'font310',
 'TkMenuFont',
 'TkIconFont',
 'TkTextFont',
 'TkDefaultFont')

更新:

我尝试过使用Tkinter字体,然后使用相应的字体文件创建PIL FreeType字体对象,但度量值仍然不同

我被难住了

text = "Where are my beards?"

### PIL Measurement ###

# The location of the fontfile corresponding to 'courier 10 pitch'
fontpath = '/usr/share/fonts/X11/Type1/c0419bt_.pfb'

font = ImageFont.FreeTypeFont(font=fontpath, size=80)

im = Image.new("RGBA", (1092, 1456), (0, 0, 0))
draw = ImageDraw.Draw(im)
draw.multiline_text((0,0), text, (255, 255, 255), font=font)
multi_size = draw.multiline_textsize(text, font=font)
print(f"multi size: {multi_size}\n")
w,h = font.getsize_multiline(text)
im.close()
del im
print(f'Width: {w}, Height: {h}\n')
#print font name
print(font.getname())

PIL测量的输出

multi size: (960, 69)

Width: 960, Height: 69

('Courier 10 Pitch', 'Regular')

Tkinter字体测量

fname = 'courier 10 pitch'
font = tkFont.Font(family=fname, size=80)

(w,h) = (font.measure(text),font.metrics("linespace"))
print(f'Width: {w}, Height: {h}\n')
print(f'{ sorted([k, v] for k,v in font.actual().items()) }')

Tkinter测量输出:

Width: 1280, Height: 124

[['family', 'courier 10 pitch'], ['overstrike', 0], ['size', 80], ['slant', 'roman'], ['underline', 0], ['weight', 'normal']]

PIL测量的Width: 960, Height: 69与Tkinter测量的Width: 1280, Height: 124有很大差异

我相信Tkinter测量是准确的,但我不能依赖于在无头服务器上使用Tkinter显示(例如)

如果我没有弄错的话,这两个度量应该是相同的,因为我对这两个度量使用了相同的字体文件

有什么想法吗


Tags: textimportsizepiltkinter字体widthfname