Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/327.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ssis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 为什么Tkinter中字符串的计算宽度和高度(以像素为单位)因平台而异?_Python_Fonts_Cross Platform_Size_Tkinter - Fatal编程技术网

Python 为什么Tkinter中字符串的计算宽度和高度(以像素为单位)因平台而异?

Python 为什么Tkinter中字符串的计算宽度和高度(以像素为单位)因平台而异?,python,fonts,cross-platform,size,tkinter,Python,Fonts,Cross Platform,Size,Tkinter,我有一个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 [("

我有一个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 Batcheld提到这一点后,我发现不同平台的字体大小不同。只要你坚持使用Tkinter,它可能不会破坏交易,Tkinter本身也会保持一致。但是my不使用Tkinter来执行实际的绘图:它只依赖于字体大小计算来生成输出(在SVG中或作为要发送到的Python脚本)。就是在那里,事情变得非常糟糕:

(请查看。注意,这些输出使用的主要字体不是Times,而是Trebuchet MS。)


我现在怀疑这种差异是不能用Tkinter来避免的。您还推荐哪种跨平台解决方案?

您没有做错任何事情:不同平台的字体大小确实不同


我不知道为什么Python版本很重要,但是差别只有一个像素,所以可能是不同的舍入或相同字体的不同呈现。

您有两个问题。让我们一次解决一个问题

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的字体测量特性进行了一些更改。假设这些更改是改进,我认为可以安全地假设您从Python2.6获得的数字比从2.5获得的数字更准确

2:mac上的python 2.6和PC上的python 2.6之间的区别

显然,从你的屏幕截图中可以看出,电脑使用了更大的字体,因此你可以得到更大的测量数字。问题是,为什么?您正在以点(1/72英寸)为单位指定字体大小。为了让Tk(或任何渲染系统)渲染字体,它需要知道实际显示上每英寸有多少像素。这在不同的系统上会有所不同,底层操作系统并不总是给Tk一个准确的数字来进行计算

从历史上看,苹果和微软已经在72ppi和96ppi上进行了标准化,而不考虑实际显示,因此数字总是会有所不同。有关mac和windows计算像素密度的差异的更多信息,请参阅维基百科上的文章

您可以尝试通过以像素而不是点为单位指定字体来解决此问题。您可以使用负数作为字体大小


最后,您可以添加到小示例代码中的一件事是打印出
font.actual()
命令的结果——您可能会看到windows和mac设备之间的不同之处,这可以解释其中的差异。这会准确地告诉您Tk使用的是哪种字体

在搜索了好几年后,我终于找到了一种方法,可以获得任意字体和大小的文本的宽度

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")
我所做的这一行证明了这适用于任何字体

据我所知,我已经对不同字体和大小的字体进行了测试

这是输出的图片:

您是否拍摄了这些字体的文本截图,并将其与您获得的值进行比较?我不知道您希望有什么样的“跨平台”解决方案。。。不同的平台和硬件使用不同的字体分辨率和字体渲染算法。我几乎不认为你能对所有这些问题都得到一个固定的答案。如果可以的话,请更新这些图片,因为它们现在已经消失了。@Nae,确实,对此感到抱歉:(TinyGrab现在似乎死了。Google没有给我带文件名的图片,Wayback机器告诉我:“没有为这个域捕获URL”对于这个SO页面。还有其他选项吗?我没有本地副本。@Aristide我不知道是否有。python版本很重要,因为tk版本很重要——字体度量在tk 8.4.x和8.5.x之间发生了变化(分别由python 2.5和2.6使用的版本)。非常感谢您的回答!您让我了解并解决了这两个问题。第一个问题来自我的Python 2.6版本:即2.6.1,它实际上存在一个关于字体度量的回归错误:更新到Python 2.6.5是一个简单的解决方案。当我使用负数指定字体的大小。这个行为实际上是在TK文档中解释的,我不知道。现在所有的石头都很感激!“阿里斯蒂德:如果我的答案或任何其他的答案对你有帮助,请考虑把答案标记为“被接受”——这是你作为问答者的职责的一部分。你的答案确实帮助了我。我已经把它标记为我们。我很抱歉,但在我余下的职责中,系统一直在说:“你可以接受这个答案,并在10小时内奖励你的赏金”。我想至少会延迟24小时。请放心,我明天会很乐意重试!但是字体大小仍然是以点为单位测量的吗?它与屏幕分辨率有关系吗?@CoolCloud:是的,字体通常以点为单位定义。但是不同的显示器有不同的像素密度。并非所有的显示器都是真正的72dpi。这将停止所有认为键入WWW很有趣的用户都认为它不适合在屏幕上显示!!!!!!!!!!!