Tkinterで画像や図形を描くためのキャンバス(Canvas)ウィジェットについて解説します。このウィジェットでは線や円などの図形を作成して表示することができるほか、画像の表示、スクロールも可能です。
目次
キャンバス(Canvas)の生成・配置
Canvas は Tkinterのウィジェットクラスの1つで、線や円などの図形や画像を表示することができます。
canvasウィジェットを生成して配置するには他のウィジェット同様次のように記述します。
import tkinter as tk # tk.Frameを継承したApplicationクラスを作成 class Application(tk.Frame): def __init__(self, master=None): super().__init__(master) # ウィンドウの設定 self.master.title("ウィンドウのタイトル") self.master.geometry("800x600") # ウィンドウサイズ(幅x高さ) # 実行内容 self.pack() self.create_widget() # create_widgetメソッドを定義 def create_widget(self): # canvasウィジェットを作成 self.canvas = tk.Canvas(self.master, width=600, height=400, bg="gray") # canvasウィジェットを作成 self.canvas.pack() # canvasウィジェットを配置 if __name__ == "__main__": root = tk.Tk() app = Application(master=root) app.mainloop()
800×600のウィンドウの中に600×400のCanvasを配置してみました。色が濃くなっている部分がCanvasウィジェットです。
これだけだとわかりにくいので図形を配置してみましょう。
図形の描画
Canvasウィジェットではメソッドを使って次の図形を描くことができます。
メソッド | 図形 |
---|---|
create_line() | 直線(折れ線) |
create_oval() | 楕円 |
create_arc() | 円弧 |
create_rectangle() | 矩形 |
create_polygon() | 多角形 |
実際にいくつか図形を描いてみましょう。
import tkinter as tk # tk.Frameを継承したApplicationクラスを作成 class Application(tk.Frame): def __init__(self, master=None): super().__init__(master) # ウィンドウの設定 self.master.title("ウィンドウのタイトル") self.master.geometry("800x600") # ウィンドウサイズ(幅x高さ) # 実行内容 self.pack() self.create_widget() # create_widgetメソッドを定義 def create_widget(self): # canvasウィジェットを作成 self.canvas = tk.Canvas(self.master, width=600, height=400, bg="gray") # canvasウィジェットを作成 # 始点10,10から対角点100,100に沿って、線の太さ10の楕円を描き、中を白く塗りつぶす self.canvas.create_oval(10, 10, 100, 100, width=10, fill="white") # 円弧 self.canvas.create_arc(120, 120, 210, 210, width=5, fill="red") # 矩形 self.canvas.create_rectangle(230, 10, 320, 100, width=5) # 多角形(指定した座標の数の分だけ頂点を持つ) self.canvas.create_polygon(340, 120, 450, 210, 230, 210, width=5, fill="yellow") self.canvas.pack() if __name__ == "__main__": root = tk.Tk() app = Application(master=root) app.mainloop()
このように様々な図形を自由に描くことができます。
画像の描画
Canvasウィジェットでは画像ファイルを表示することもできます。
実際にやってみましょう。
import tkinter as tk # tk.Frameを継承したApplicationクラスを作成 class Application(tk.Frame): def __init__(self, master=None): super().__init__(master) # ウィンドウの設定 self.master.title("ウィンドウのタイトル") self.master.geometry("800x600") # 実行内容 self.pack() self.create_widget() # create_widgetメソッドを定義 def create_widget(self): # canvasウィジェットを作成 self.canvas = tk.Canvas(self.master, width=800, height=600) # canvasウィジェットを作成 self.canvas.pack() # canvasウィジェットを配置 self.bg_img = tk.PhotoImage(file="img/bg_img.png") # 画像ファイルのオブジェクトを作成 self.canvas.create_image(0, 0, anchor="nw", image=self.bg_img) # 画像を描画 # この時anchorを指定しないと原点がキャンバスオブジェクトの中央になってしまう。 if __name__ == "__main__": root = tk.Tk() app = Application(master=root) app.mainloop()
Canvasに画像を表示するには、PhotoImageクラスを使って画像ファイルのオブジェクトを作成してから、create_imageメソッドで描画します。
この時オプション引数でanchor(原点)を指定しないと、キャンバスウィジェットの中央が原点になってしまうので注意しましょう。
PhotoImageクラスで扱える画像のフォーマットは以下のとおりです。
- PGM
- PPM
- GIF
- PNG
画像の削除、切り替え
せっかくなのでボタンウィジェットを組み合わせて画像を消したり表示したり、切り替えたりできるようにしてみましょう。
キャンバスウィジェットで画像を消すには予め画像描画時にタグを付けておき、deleteメソッドで指定したタグが付けられた画像をキャンバス上から消去します。
import tkinter as tk # tk.Frameを継承したApplicationクラスを作成 class Application(tk.Frame): def __init__(self, master=None): super().__init__(master) # ウィンドウの設定 self.master.title("ウィンドウのタイトル") self.master.geometry("800x700") # 実行内容 self.pack() self.create_widget() # create_widgetメソッドを定義 def create_widget(self): # canvasウィジェットを作成 self.canvas = tk.Canvas(self.master, width=800, height=700) self.canvas.pack() self.bg_img1 = tk.PhotoImage(file="img/bg_img1.png") self.bg_img2 = tk.PhotoImage(file="img/bg_img2.png") # 画像2もキャンバス作成時に読み込んでおく self.canvas.create_image(0, 0, anchor="nw", image=self.bg_img1, tag="img1") # オプション引数tagでタグを付ける # ボタンを作成・配置 delete_button = tk.Button(self.master, text="画像を消去", font=("MSゴシック体", "20","bold"), command=self.delete_img) delete_button.place(x=100, y=620) create_button1 = tk.Button(self.master, text="画像1を表示", font=("MSゴシック体", "20","bold"), command=self.create_img1) create_button1.place(x=300, y=620) create_button2 = tk.Button(self.master, text="画像2を表示", font=("MSゴシック体", "20","bold"), command=self.create_img2) create_button2.place(x=510, y=620) # 各ボタンが押された時の処理 def delete_img(self): self.canvas.delete("img1", "img2") # 指定したタグが付いている画像を消去 def create_img1(self): self.canvas.create_image(0, 0, anchor="nw", image=self.bg_img1, tag="img1") # 画像1にimg1タグを付けて描画 def create_img2(self): self.canvas.create_image(0, 0, anchor="nw", image=self.bg_img2, tag="img2") # 画像2にimg2タグを付けて描画 if __name__ == "__main__": root = tk.Tk() app = Application(master=root) app.mainloop()
25行目の最初に画像を描画する際、42行目と45行目のボタンクリック時に画像を描画する際にオプション引数tagを使って画像にタグを付けておきます。
27~35行目で各ボタンを作成・配置。
37~45行目で各ボタンが押された時の処理を記述しています。
ボタンウィジェットの詳しい使い方については下記の記事をご参照ください。
画像のとおりですが、「画像を削除」ボタンを押すと画面上の画像が全て消え、「画像1を表示」ボタンを押すと画像1が、「画像2を表示」ボタンを押すと画像2がそれぞれキャンバスに描画されます。
キャンバス(Canvas)で使えるオプション引数
属性 | 説明 | 値 |
---|---|---|
anchor | ウィジェットを配置する位置を指定します |
tk.CENTER(中央) tk.W(左寄せ) tk.E(右寄せ) tk.N(上寄せ) tk.S(下寄せ) tk.NW(左上) tk.SW(左下) tk.NE(右上) tk.SE(右下) |
width | キャンバスの幅を指定します。 | 数値 |
height | キャンバスの高さを指定します | 数値 |
bg or background | 背景の色を指定します | red,blue,grayなど |
bd or borderwidth | キャンバスの枠の幅を指定します | 数値 |
relief | ボーダー部分の浮き彫りを指定します | flat,raised,sunken,groove,ridge |
scrollregion | スクロールする領域のサイズを指定します。 | |
xscrollcommand | 横方向にスクロールするスクロールバーの スクロールバー.set を指定します。 | |
xscrollincrement | 横方向のスクロールバーの矢印をクリックしたときの移動量を指定します。 | |
yscrollcommand | 縦方向にスクロールするスクロールバーの スクロールバー.set を指定します。 | |
yscrollincrement | 縦方向のスクロールバーの矢印をクリックしたときの移動量を指定します。 |