今日も見に来てくださって、ありがとうございます。石川さんです。
Canvasにテキストを書いたときに、その大きさや、座標はどうなるのかな、と、ちょっと気になったので調べてみました。こちらのサイトを参考にさせていただきました。
出力イメージ
出力イメージはこんな感じになります。
作成したスクリプト
今回作成したスクリプトは以下のようになりました。
import tkinter as tk class App(tk.Tk): def __init__(self): super().__init__() self.title("Canvas Text") self.geometry("400x200") c = tk.Canvas(self, bg="white") c.pack(fill=tk.BOTH) t1 = c.create_text(70, 30, text="1st text", font=("",24)) c.create_rectangle(c.bbox(t1)) x0, y0, x1, y1 = c.bbox(t1) c.create_line(x1, y1, x1 + 30, y1 + 30, arrow=tk.FIRST) description = "bboxは、テキストを囲む箱の座標を戻します。" c.create_text(x1 + 30, y1 + 30, text=description, anchor=tk.W) x, y = c.coords(t1) c.create_line(x, y, x + 70, y + 70, arrow=tk.FIRST, fill="red") description = "coordsは中心点を戻します。" c.create_text(x + 70, y + 70, text=description, anchor=tk.NW, font=("",9)) width = tk.font.Font(c,font=("",9)).measure(description) height = tk.font.Font(c,font=("",9)).metrics("linespace") c.create_line(x + 70, y + 70 + height, x + 70 + width, y + 70 + height) if __name__ == "__main__": app = App() app.mainloop()
解説
もろもろのアプリケーションウィンドウをつくるところは端折って、まずは9行目でキャンバスを作成しています。作成時のbg=”white”で背景色を白に、packのfill=tk.BOTHでウィンドウサイズに合わせます。
12行目で”1st text”と最初のテキストを作成しています。座標にx=70、y=30を指定しています。ちょっと大きめになるようにフォントのサイズを24と指定しています。フォント名を指定することで変更することもできますが、初期値のままにしておきたかったので、””を指定しています。
13行目のcreate_rectangleを使って、矩形を描画しています。指定する座標はbboxで取得していますが、bboxはテキストを囲む矩形の左上の座標と右下の座標を取得します。14行目では説明用の線を引くために、もう一度bboxを呼び出して座標をアンパックして取り出しています。ぼくの環境では、それぞれ、(17, 14, 124, 47)がセットされていました。
15行目で矢印付きの直線を斜め下に弾いています。arrow=tk.FIRSTで開始座標が矢印になっています。
18行目でcoordsを使っていますが、これはテキストを作成するときに指定した座標を戻します。この場合はテキストの中心点になっています。これは、テキスト作成時にanchorを指定しなかったので、デフォルト値のtk.CENTERが指定されたためです。他にどこを指定するかというのは、こちらが参考になりました。
ちなみにぼくの環境ではこのcoordsの戻り値、テキスト作成時の座標に70と30を指定した結果、(70.0、30.0)になっていました。coordsは小数点以下が有効になっているようです。試しにcreate_textの座標を70.5とか、70.9999とかに設定したら、その値をきちんと保持していることが確認できました。有効桁数がどれくらいなのか、どうやってこの座標値を扱っているのか、ちょっぴり気になります。
22行目は、テキスト出力の横幅をどうやって計算すればいいのか、というのを調べた結果です。これはあちこち探しまわって、結局ここを参考にしたと思います。テキストに下線を引いてちゃんと幅が一致していることを確認しました。最初はfont=(“”,9)というのを指定していなかったのですが、そうすると、最初にcreate_textした時のサイズ、24がなぜか取得できてしまったので、テキストとともにわざわざ設定することにしました。今回はとりあえず幅が求まって満足したので、なぜそんなことになるのかという原因までは調査しませんでした。
bboxがあるのでいったん出力してしまえばテキストの描画幅は座標から計算できるのですけど、幅をもとに位置決めをしたい要望があったので、先に計算して求める方法を探し出しました。
まとめ
これでキャンバス上にテキストと線を自由自在にひくことができるようになりました。いや、なったはずです!(笑)