Python(tkinter画像入れ替え)

python

PythonでGUIアプリの作成できるtkinter。今回はこのtkinterを使った処理の中から画像の入れ替えにフォーカスを当てよう。

準備

○最初に今回のプロジェクトフォルダをimagelessonとしてデスクトップ(任意の場所)に作成する。
○次に以下のファイルをダウンロード->解凍して中に入っている画像3枚をimagelessonの直下に配置する。

作成

メインウインドウの作成

土台となるメインウィンドウを以下のように作成しよう。(main1.py)

import tkinter as tk
	
root=tk.Tk()
root.geometry('700x560')
root['bg']='lightgrey'
root.mainloop()

以下のようにグレーに塗られた700×500のウィンドウが表示されればOKだ。

さて、どう画像を配置していくかだが今回はCanvasを作ってそこに描画していこう。

import tkinter as tk
	
root=tk.Tk()
root.geometry('700x560')
root['bg']='lightgrey'
#画像用のキャンバス作成
canvas=tk.Canvas(width=640,height=426)
#キャンバスを設置(上下に20の余白)
canvas.pack(pady=20)
#画像を用意
photo1=tk.PhotoImage(file='cat1.png')
#画像を描画(中点x,中点y,画像)
canvas.create_image(320,213,image=photo1)
root.mainloop()

画像と同じ大きさのキャンバスを作成し、それをrootに配置している。
画像を表示するには画像の準備と描画の2ステップが必要なのがポイント
実行してみよう。

画像と同じ大きさにキャンバスを作成したにもかかわらず白い隙間が出来てしまっている。以下のように修正しよう。

import tkinter as tk
	
root=tk.Tk()
root.geometry('700x560')
root['bg']='lightgrey'
#画像用のキャンバス作成
canvas=tk.Canvas(root,width=640,height=426,bd=0, highlightthickness=0, relief='ridge')
#キャンバスを設置(上下に20の余白)
canvas.pack(pady=20)
#画像を用意
photo1=tk.PhotoImage(file='cat1.png')
#画像を描画(中点x,中点y,画像)
canvas.create_image(320,213,image=photo1)
root.mainloop()

Canvasを作成する際、widthとheightを指定してもそれを包むようにborderが作成されてしまっている。その余計な装飾を除去した。実行してみよう。

OK!

画像を追加してみよう。以下のように修正する。

import tkinter as tk
	
root=tk.Tk()
root.geometry('700x560')
root['bg']='lightgrey'
canvas=tk.Canvas(root,width=640,height=426,bd=0, highlightthickness=0, relief='ridge')
canvas.pack(pady=20)
photo1=tk.PhotoImage(file='cat1.png')
canvas.create_image(320,213,image=photo1)
photo2=tk.PhotoImage(file='cat2.png')
canvas.create_image(340,233,image=photo2)
root.mainloop()

もう一枚画像を作成し、描画した。その際にx,y共に20ずつオフセットさせて重なり具合をわかりやすくしている。このように同じ位置にcreate_imageされた画像はどんどん積み重なっていく

不要になった画像を消すにはどうすればよいのだろうか?
以下のように追記する

import tkinter as tk
	
root=tk.Tk()
root.geometry('700x560')
root['bg']='lightgrey'
canvas=tk.Canvas(root,width=640,height=426,bd=0, highlightthickness=0, relief='ridge')
canvas.pack(pady=20)
photo1=tk.PhotoImage(file='cat1.png')
canvas.create_image(320,213,image=photo1)
photo2=tk.PhotoImage(file='cat2.png')
canvas.create_image(340,233,image=photo2,tag='p2')
canvas.delete('p2')
root.mainloop()

create_imageする際にタグを設定して、そのタグをdeleteすることによって画像を削除できる。

ボタンの設置

今回はボタンを設置して、そのボタンを押すごとに画像が切り替わるようにしてみよう。以下のように追記する。

import tkinter as tk
	
root=tk.Tk()
root.geometry('700x560')
root['bg']='lightgrey'
canvas=tk.Canvas(root,width=640,height=426,bd=0, highlightthickness=0, relief='ridge')
canvas.pack(pady=20)
photo1=tk.PhotoImage(file='cat1.png')
canvas.create_image(320,213,image=photo1)
photo2=tk.PhotoImage(file='cat2.png')
canvas.create_image(340,233,image=photo2,tag='p2')
canvas.delete('p2')
btn=tk.Button(text='Click')
btn.pack(ipadx=10,ipady=5)
root.mainloop()

Button要素を作成し、それをpackで配置した。このようにpackで配置すると基本的にはウィジッドを縦に並べていく。ipadxというのは内側の余白だ(cssでいうpadding-leftとpadding-right)
実行してみよう、画像の下にボタンが配置された。(画像とボタンの隙間はキャンバスのpady=20の影響)

クリックイベントの登録

ボタンを押したら~の処理を作成しよう。今回は手始めとしてボタンを押したら画像が消えるようにしてみる。以下のように修正

import tkinter as tk

def btn_click():
	canvas.delete('p1')	

root=tk.Tk()
root.geometry('700x560')
root['bg']='lightgrey'
canvas=tk.Canvas(root,width=640,height=426,bd=0, highlightthickness=0, relief='ridge')
canvas.pack(pady=20)
photo1=tk.PhotoImage(file='cat1.png')
canvas.create_image(320,213,image=photo1,tag='p1')
photo2=tk.PhotoImage(file='cat2.png')
canvas.create_image(340,233,image=photo2,tag='p2')
canvas.delete('p2')
btn=tk.Button(text='Click',command=btn_click)
btn.pack(ipadx=10,ipady=5)
root.mainloop()

まず、画像にp1というタグを付与して、上部にてbtn_clickという関数を定義している。
この関数の内容はp1タグが付いている画像を削除するものだ。
あとは、ボタンのcommadにその関数を登録する。

実行してみよう。クリックすると画像が消えることがわかる。

画像が切り替わる仕組みを入れる

ではボタンを押すと画像が切り替わる仕組みを作ろう。5行(下の13-19)をコメントアウトし、以下のように修正する。

import tkinter as tk

index=0 #画像のindexはグローバルで管理する

def btn_click():
	canvas.delete('p1')	

root=tk.Tk()
root.geometry('700x560')
root['bg']='lightgrey'
canvas=tk.Canvas(root,width=640,height=426,bd=0, highlightthickness=0, relief='ridge')
canvas.pack(pady=20)
"""
photo1=tk.PhotoImage(file='cat1.png')
canvas.create_image(320,213,image=photo1,tag='p1')
photo2=tk.PhotoImage(file='cat2.png')
canvas.create_image(340,233,image=photo2,tag='p2')
canvas.delete('p2')
"""
photos=[
	tk.PhotoImage(file='cat1.png'),
	tk.PhotoImage(file='cat2.png'),
	tk.PhotoImage(file='cat3.png'),
]
canvas.create_image(320,213,image=photos[index],tag='p1')
btn=tk.Button(text='Click',command=btn_click)
btn.pack(ipadx=10,ipady=5)
root.mainloop()

画像をリストに入れて、表示する画像をindexを使って指定することにした。
ここまでで実行すると先程と同じ動きになる。

いよいよ仕上げだ、以下のように修正する。

import tkinter as tk

index=0 #画像のindexはグローバルで管理する

def btn_click():
	global index
	index=(index+1) % len(photos)
	canvas.delete('p1')	
	canvas.create_image(320,213,image=photos[index],tag='p1')

root=tk.Tk()
root.geometry('700x560')
root['bg']='lightgrey'
canvas=tk.Canvas(root,width=640,height=426,bd=0, highlightthickness=0, relief='ridge')
canvas.pack(pady=20)
photos=[
	tk.PhotoImage(file='cat1.png'),
	tk.PhotoImage(file='cat2.png'),
	tk.PhotoImage(file='cat3.png'),
]
canvas.create_image(320,213,image=photos[index],tag='p1')
btn=tk.Button(text='Click',command=btn_click)
btn.pack(ipadx=10,ipady=5)
root.mainloop()

クリックするごとにindexを増やし、古い画像を消したあとに新しい画像を作り直している。%(剰余記号)を使ってindexを循環させるのはお決まりのパターンだ。このときlen()を使っておくと画像を増やす際に配列に追加するだけですべてOKとなる。

完成

以上で完成だ。GUIを使ったアプリは画像の扱いがポイントとなる。しっかり基本を抑えておこう。 なお、現状(tkinter3.6)ではpngしか扱えない、jpegを扱う場合にはPIL(Python Imaging Library)を使う必要があることも覚えておこう。

python
スポンサーリンク
シェアする
mjpurinをフォローする

コメント

タイトルとURLをコピーしました