我有一个Python脚本,需要计算以任意字体显示的任意字符串的确切大小,以生成简单的图表。我可以轻松地使用Tkinter。
import Tkinter as tk
import tkFont
root = tk.Tk()
canvas = tk.Canvas(root, width=300, height=200)
canvas.pack()
(x,y) = (5,5)
text = "yellow world"
fonts = []
for (family,size) in [("times",12),("times",24)]:
font = tkFont.Font(family=family, size=size)
(w,h) = (font.measure(text),font.metrics("linespace"))
print "%s %s: (%s,%s)" % (family,size,w,h)
canvas.create_rectangle(x,y,x+w,y+h)
canvas.create_text(x,y,text=text,font=font,anchor=tk.NW)
fonts.append(font) # save object from garbage collecting
y += h+5
tk.mainloop()
结果似乎取决于Python和/或系统的版本:
在Ned Batchelder提到它之后,我发现字体的大小因平台而异。只要你坚持与自己保持一致的Tkinter,它可能不是一个交易破坏者。但是我的complete program 不使用Tkinter来执行实际绘图:它只依赖于其字体大小计算来生成输出(在SVG中或作为Python脚本发送到{{ 3}})。事情就是这样:
(请查看Output of mocodo http://grab.by/grabs/f67b951d092dd1f4f490e1469a53bca2.png。请注意,用于这些输出的主要字体不是Times,而是Trebuchet MS。)
我现在怀疑Tkinter无法避免这种差异。您会推荐哪种其他跨平台解决方案?
答案 0 :(得分:19)
你有两个问题。让我们一次解决一个问题
1:同一平台上具有相同字体的python 2.5和2.6之间的差异
这两个版本的python使用不同版本的tk。在我的Mac机上,2.5使用tk版本8.4.19,2.6使用8.5.7。在tk的8.5.2版本中,对tk的字体测量功能进行了一些更改。假设改变是改进的,我认为可以安全地假设从python 2.6获得的数字比从2.5获得的数字更准确。
2:mac上的python 2.6和PC上的2.6之间的区别。
显然,根据您提供的屏幕截图,PC使用的是更大的字体,因此您可以获得更大的测量数字。问题是,为什么?您以磅为单位指定字体大小(1/72英寸)。为了让Tk(或任何渲染系统)渲染字体,它需要知道实际显示器上一英寸的像素数。这在不同的系统上会有所不同,并且底层操作系统并不总是给Tk提供准确的数字以进行计算。
从历史上看,Apple和Microsoft已经标准化了72ppi和96ppi,无论实际显示如何,因此数字总是不同的。有关mac和windows如何计算像素密度差异的详细信息,请参阅维基百科上的Dots Per Inch文章。
您可以尝试通过指定字体而不是点数来解决此问题。您可以使用字母大小的负数来执行此操作。
最后,您可以添加到您的小示例代码中的一件事是打印出font.actual()
命令的结果 - 您可能会在Windows和Mac框之间看到不同的内容,这可以解释其中的差异。这告诉您Tk使用的确切字体。
答案 1 :(得分:7)
搜索了几年后,我终于找到了一种方法来获得任何字体和大小的文字宽度!
from tkinter import *
Window = Tk()
Window.geometry("500x500+80+80")
frame = Frame(Window) # this will hold the label
frame.pack(side = "top")
# CALCULATE:
measure = Label(frame, font = ("Purisa", 10), text = "The width of this in pixels is.....", bg = "yellow")
measure.grid(row = 0, column = 0) # put the label in
measure.update_idletasks() # this is VERY important, it makes python calculate the width
width = measure.winfo_width() # get the width
# PROOF IT WORKS:
canvas = Canvas(frame, width = 400, height = 200, bg = "light green")
canvas.grid(row = 1, column = 0, columnspan = 100) # collumnspan is 100 so that the line lines up with the text
line = canvas.create_line(0, 10, width, 10, width = 4) # make a line the same length as the text
canvas.create_text(10, 20, font = ("Purisa", 10), text = "... "+str(width)+" Pixels", anchor = "nw")
我所做的一行证明这适用于任何字体。
据我所知,我已针对不同的字体和大小对此进行了测试。
这是输出的图片:
答案 2 :(得分:5)
你没有做错任何事: 字体的大小因平台而异。
我不确定为什么Python版本很重要,但差异只是一个像素,所以它可能是不同的舍入或相同字体的不同渲染。