この記事では、TkinterのCanvasを作成する方法を学びましょう。
Tkinterとは?
TkinterはGUI(Graphical User Interface)を作成するためのPythonのインターフェイスです。
このライブラリはクロスプラットフォームであり、アプリケーションコードがプラットフォームに依存しないので、Python開発者にとって理想的な選択肢です!
このライブラリの最大の特徴は、Pythonにプリインストールされていることです。
そのため、これを別途インストールする必要はありません。
しかし、念のため、Tkinterが我々のシステムで正しく動作しているかどうか確認しておきましょう。
Windowsのコマンドプロンプト(Linux/MacではBash)で、次のように入力します。
python -m tkinter |
このようなサンプルウィンドウが表示されれば、Tkinterが動作していることがわかります。
- ! Tkinter CheckTkinter チェック
そして、このライブラリを使いたい場合は、たった1行でOK!
import tkinter
|
さて、いよいよTkinterを使った最初のプログラムを書き始めます。
今回は、画面に画像を表示する簡単なプログラムを作成します。
それでは、アプリケーションを構築するための最初のステップを始めましょう。
Tkinterのキャンバスを作成する
ステップ1: アプリケーションとマスターオブジェクトハンドルの作成
canvas を作成する前に、Python の Tkinter オブジェクトをインスタンス化する必要があります。
デフォルトのコンストラクタはTkinterオブジェクトをインスタンス化します。
このオブジェクトは通常、ルートオブジェクト(マスターオブジェクト)と呼ばれます。
これは、GUIアプリケーションがこのオブジェクトを通してすべての呼び出しを行うからです。
アプリケーションはこのオブジェクトなしには実行できません。
マスターオブジェクトを作成するには、以下のようにします。
import tkinter as tk
# Create our master object to the Applicationmaster = tk.Tk()
|
これでマスターオブジェクトが作成されました。
さて、アプリケーションを実行するために、通常、このようなプログラムはイベントループとして設計されています。
ここで、アプリケーションがこのオブジェクトを使用し、イベントループに渡すことができるように、アプリケーションへのハンドルも必要です。
クラス tk.Frame がこれを提供してくれます。
そこで、このクラスを継承した Application クラスを作成します。
これで、アプリケーションオブジェクトから直接メインループを呼び出すことができるようになりました。
class Application(tk.Frame):
def __init__(self, master=None):
# We need the master object to
# initialize important stuff
super().__init__(master) # Call tk.Frame.__init__(master)
self.master = master # Update the master object after tk.Frame() makes necessary changes to it
|
アプリケーションクラス Application を作成します。
このクラスのコンストラクタはベースクラス (tk.Frame) のコンストラクタを呼び出し、マスターオブジェクトを渡すことで、重要なものを初期化することができます。
さて、super.__init__(master) は実際に master オブジェクトを変更するので、自分自身のコピーを最新のものに更新しておきます。
アプリケーションオブジェクト app のメインプログラムは app.mainloop() と呼ばれるメインイベントループの下で実行されます。
これは、Pythonからあなたのマシン上の低レベルの言語へのすべての呼び出しを実際に行うものです。
メインループを開始するには、この関数を呼び出すだけです。
import tkinter as tk
class Application(tk.Frame):
def __init__(self, master=None):
# We need the master object to
# initialize important stuff
super().__init__(master) # Call tk.Frame.__init__(master)
self.master = master # Update the master object after tk.Frame() makes necessary changes to it
# Create our master object to the Applicationmaster = tk.Tk()
# Create our application objectapp = Application(master=master)
# Start the mainloopapp.mainloop() |
さて、このプログラムを実行すると、次のような出力が得られます。
canvas = tk.Canvas(master_object, bg="blue", width=canvas_width, height=canvas_height)
|
パート2:Tkinter Canvasの作成
さて、Canvas を作成する準備が整いました!
tk.Canvas()` メソッドを使うと、Canvas を作成することができます。
初期設定は以下の通りです。
import tkinter as tk
class Application(tk.Frame):
def __init__(self, master=None):
# We need the master object to
# initialize important stuff
super().__init__(master) # Call tk.Frame.__init__(master)
self.master = master # Update the master object after tk.Frame() makes necessary changes to it
def createCanvas(self, canvas_width, canvas_height):
# Create our canvas (blue background)
canvas = tk.Canvas(self.master, bg="blue", width=canvas_width, height=canvas_height)
return canvas
# Create our master object to the Applicationmaster = tk.Tk()
# Create our application objectapp = Application(master=master)
canvas = app.createCanvas(300, 300)
# Pack items into the canvascanvas.pack()# Start the mainloopapp.mainloop() |
この行は背景が青で、指定された幅と高さ(ピクセル)を持つ canvas オブジェクトを作成します。
しかし、ここではまだループを直接開始することができません。
canvas の変更を適用して、オブジェクトを canvas にパックする必要があります。
これには canvas.pack() が必要です。
これで、メインループの中で空の canvas を表示できるようになりました。
img = tk.PhotoImage(file="debian.png") # Create our PhotoImage object
image = canvas.create_image(100, 100, anchor=NW, image=img) # Create the image on our canvas
|
では、このプログラムを実行してみましょう。
def addImage(self, canvas, filename, image_x, image_y, direction=tk.NW):
self.img = tk.PhotoImage(file=filename) # Create our PhotoImage object
canvas.create_image(image_x, image_y, anchor=direction, image=self.img) # Create the image on our canvas
return canvas
|
素晴らしい! これは期待通りに動いているようです。
では、キャンバス上でさらにいろいろなことをしてみましょう。
この Debian Linux の画像をアプリケーションに表示してみましょう。
import tkinter as tk
class Application(tk.Frame):
def __init__(self, master=None):
# We need the master object to
# initialize important stuff
super().__init__(master) # Call tk.Frame.__init__(master)
self.master = master # Update the master object after tk.Frame() makes necessary changes to it
def createCanvas(self, canvas_width, canvas_height):
# Create our canvas (blue background)
canvas = tk.Canvas(self.master, bg="blue", width=canvas_width, height=canvas_height)
return canvas
def addImage(self, canvas, filename, image_x, image_y, direction=tk.NW):
img = tk.PhotoImage(file=filename) # Create our PhotoImage object
canvas.create_image(image_x, image_y, anchor=direction, image=img) # Create the image on our canvas
return canvas
# Create our master object to the Applicationmaster = tk.Tk()
# Create our application objectapp = Application(master=master)
canvas = app.createCanvas(300, 300)
canvas = app.addImage(canvas, "debian.png", 50, 50)
# Pack items into the canvascanvas.pack()# Start the mainloopapp.mainloop() |
画像アイテムを作成するには tk.PhotoImage クラスを使用します。
import tkinter as tk
class Application(tk.Frame):
def __init__(self, master=None):
# We need the master object to
# initialize important stuff
super().__init__(master) # Call tk.Frame.__init__(master)
self.master = master # Update the master object after tk.Frame() makes necessary changes to it
def createCanvas(self, canvas_width, canvas_height):
# Create our canvas (blue background)
canvas = tk.Canvas(self.master, bg="blue", width=canvas_width, height=canvas_height)
return canvas
def addImage(self, canvas, filename, image_x, image_y, direction=tk.NW):
self.img = tk.PhotoImage(file=filename) # Create our PhotoImage object
canvas.create_image(image_x, image_y, anchor=direction, image=self.img) # Create the image on our canvas
return canvas
# Create our master object to the Applicationmaster = tk.Tk()
# Create our application objectapp = Application(master=master)
canvas = app.createCanvas(300, 300)
canvas = app.addImage(canvas, "debian.png", 50, 50)
# Pack items into the canvascanvas.pack()# Start the mainloopapp.mainloop() |
これをクラスの addImage() メソッドの下に配置しましょう。

さて、プログラム全体はこのようになります。

しかし、このプログラムを実行すると、また青いキャンバスだけが表示されます。
Stack Overflow のこのスレッドによると、画像オブジェクト img は Python によってガベージコレクションされ、表示されないそうです。
なぜですか?どうやら tk.PhotoImage オブジェクトがこのプロパティを持っているようです。
そこで、Pythonがすぐに捨てないようにするために、クラス内で追加の参照が必要です。
そこで、 addImage() メソッドで img を self.img に置き換えることで、問題を解決することができました。

このプログラムを実行すると、正しい出力が得られると思います。

これで問題は解決です!
これで、図形を描いたり、似たような画像を表示したりと、Tkinterでいろいろなことができるようになりました。
ドキュメントが役に立つかもしれません。
まとめ
この記事では、Tkinter Canvasについて、そしてTkinter canvasを作成し、それを画面に表示する方法について学びました。