PythonでGUIに画像を表示する

PythonのGUI(tkinter)のcanvasに画像を表示します。

目次

  1. Canvasに画像を表示する
  2. 実施例
  3. グローバル変数を使いたくない場合

Canvasに画像を表示する

PythonのGUIモジュールのtkinterには、画像を表示するウィジェットとしてcanvasというものがあります。このcanvasウィジェットにファイルから読み込んだ画像を表示します。

canvasウィジェットに画像を表示するには、tkinterのcreate_imageメソッドを使用します。

id = canvas.create_image(x, y, [activeimage], [anchor], [disableimage], [image], [state], [tags])
変数 内容
canvas   画像を表示するcanvasオブジェクト。
x int canvas内の画像の位置。x座標。
y int canvas内の画像の位置。y座標。
activeimage   省略可。
anchor str 省略可。既定値はcenter。画像を配置するときの基準。
disableimage   省略可。
image object 省略可。tkinterのPhotoImageまたはBitmapImageオブジェクト。
state   省略可。
tags   省略可。
id   アイテムID。

anchorは画像を配置するときに、画像のどの箇所をx, yで指定した座標に合わせるかを指定します。指定できる文字列は、n、ne、e、se、s、sw、w、nw、centerのいずれかです。方角で指定するわけですね。

例えば、canvasの0, 0の位置に画像の左上を合わせるときは、x=0, y=0, anchor='nw'となります。

imageにはイメージオブジェクトを指定するのですが、tkinter用のPhotoImageかBitmapImageと互換のものでなくてはなりません。

ということで、PillowのImageオブジェクトはそのまま使えません。PillowのImageTKを使ってtkinter用に変換してから使います。

実施例

画像を読み込んでcanvasで表示してみます。

読み込む画像はこの プロ生ちゃん の画像です。

元画像

コードはこんな感じです。

import tkinter
from PIL import Image, ImageTk

class Application(tkinter.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.master = master
        self.master.title('tkinter canvas trial')
        self.pack()
        self.create_widgets()

    def create_widgets(self):
        global im

        # 画像読み込み
        read_image = Image.open('test_figure.png')

        # canvas作成
        self.test_canvas = tkinter.Canvas(self, width=read_image.width, height=read_image.height)
        self.test_canvas.grid(row=0, column=0)

        # canvasに画像を表示
        im = ImageTk.PhotoImage(image=read_image)
        self.test_canvas.create_image(0, 0, anchor='nw', image=im)

global im

root = tkinter.Tk()
app = Application(master=root)
app.mainloop()

canvasウィジェットを作るところで画像の読み込みと表示をしています。

canvasを作る関数内でimをグローバル変数宣言しています。これをしないと、create_imageがイメージオブジェクトを見失うようで、canvasに画像が表示されなくなります。

関数の外でのimのグローバル宣言は無くても動くのですが、まあ、宣言しておかないと忘れそうなので。

実行するとこのようなウインドウが表示されます。

実行画面

グローバル変数を使いたくない場合

グローバル変数を使いたくない場合は、こういう方法もあります。

import tkinter
from PIL import Image, ImageTk

class Application(tkinter.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.master = master
        self.master.title('tkinter canvas trial')
        self.pack()
        self.create_widgets()

    def create_widgets(self):
        # 画像読み込み
        read_image = Image.open('test_figure.png')

        # canvas作成
        self.test_canvas = tkinter.Canvas(self, width=read_image.width, height=read_image.height)
        self.test_canvas.grid(row=0, column=0)

        # canvasに画像を表示
        im = ImageTk.PhotoImage(image=read_image)
        self.test_canvas.photo = im
        self.test_canvas.create_image(0, 0, anchor='nw', image=self.test_canvas.photo)

root = tkinter.Tk()
app = Application(master=root)
app.mainloop()

canvasオブジェクトのphotoプロパティにPhotoImageオブジェクトへの参照を持たせて、Pythonのガベージコレクションを避けるわけですね。

実行結果は前述のものと同じになります。

広告

PythonでGUIカテゴリの投稿