web-dev-qa-db-ja.com

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 [("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および/またはシステムのバージョンによって異なるようです:

Python 2.5 Mac 0S X、12倍:(63,12)、24倍:(128,24)。Python 2.6 Mac OS X、12倍:(64,14 )、24回:(127,27)。Python 2.6 Windows XP、12回:(78,19)、24回:(169,36)http://grab.by/ grabs/d24a5035cce0d8032ea4e04cb8c85959.png

Ned Batchelderがそれについて言及した後、フォントのサイズがプラットフォームごとに異なることを発見しました。 Tkinterに固執している限り、それは取引を妨げるものではないかもしれません。Tkinterはそれ自体と一貫性を保っています。しかし、私の 完全なプログラムnotTkinterを使用して実際の描画を実行しません:フォントサイズの計算に依存して、出力(SVGまたはPythonスクリプトに送信される Nodebox )として)そして、物事が本当にうまくいかないことがあります:

mocodoの出力http://grab.by/grabs/f67b951d092dd1f4f490e1469a53bca2.png

実物大の画像 をご覧ください。これらの出力に使用されるメインフォントはTimesではなく、Trebuchet MSであることに注意してください。)

私は今、そのような不一致はTkinterでは避けられないと思います。他にどのクロスプラットフォームソリューションをお勧めしますか?

30
Aristide

2つの問題があります。一度に1つずつ取り組みましょう

1:同じフォントの同じプラットフォームでのpython 2.5と2.6の違い

これらの2つのバージョンの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(または任意のレンダリングシステム)がフォントをレンダリングするには、実際のディスプレイで1インチに何ピクセルあるかを知る必要があります。これはシステムによって異なり、Tkは、計算を行うために、基盤となるOSから常に正確な数値が与えられるとは限りません。

歴史的に、AppleとMicrosoftは実際の表示に関係なく72ppiと96ppiで標準化されているため、数値は常に異なります。MacとWindowsがピクセルを計算する方法の違いの詳細については密度は、ウィキペディアの Dots Per Inch の記事を参照してください。

ポイントではなくピクセルでフォントを指定することで、これを解決してみてください。これを行うには、フォントサイズに負の数を使用します。

最後に、小さなサンプルコードに追加できることの1つは、font.actual()コマンドの結果を出力することです。ウィンドウとMacボックスで何か違いが見られる場合があります。これは、そこでの違いを説明しています。これにより、Tkが使用しているフォントが正確にわかります。

19
Bryan Oakley

年齢を検索した後、私はついにテキストの幅を任意のフォントとサイズで取得する方法を見つけました!

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

私が作成した行は、これがどのフォントでも機能することを証明しています。

私が知っている限り、これをさまざまなフォントとサイズでテストしました。

これは出力の写真です: This is a picture of the output

7
Tom Fuller

あなたは何も悪いことをしていません:フォントのサイズしますプラットフォームごとに異なります。

Pythonバージョンが重要である理由はわかりませんが、違いは1ピクセルしかないため、同じフォントの丸めやレンダリングが異なる可能性があります。

5
Ned Batchelder