目的
pythonでは簡単にGUIを作成できるライブラリとしてtkinterがあります。tkinterでは画像などの表示も可能ですが、何かをトリガにして表示している画像を自動で切り替えることはできるのか、ということで試します。
使用ライブラリ
今回は主に以下の3つを使用することにしました。
- tkinter
python上でGUIを構築するためのライブラリで、今回のメインライブラリになります。
- PIL(pillow)
python上で画像を処理するためのライブラリです。今回は画像を一定時間毎に切り替えることを試すので、そもそも画像を読み込んで処理するために使います。
- threading
画像を自動切換えする仕掛けを作るために使用します。詳しくは後述します。
なお、Anaconda3の環境では、デフォルトですべてimportできる状態になってますので、新たにpip installする必要はありません。
Step1 : による画像表示
まずは、基本的なtkinterの使い方として、単に画像を表示させるための関数を用意します。
具体的には以下のようなコードで画像を表示させる関数(show_image)を作ることができます。
#必要ライブラリの読み込み import sys import tkinter from PIL import Image, ImageTk import time #画像を表示させるための関数定義 def show_image(): #tkinterのTKインスタンス用意 root = tkinter.Tk() root.title('test') root.geometry("400x300") #画像読み込み(yourimage.jpgは任意の画像へのパスにすること) img = Image.open('yourimage.jpg') img = ImageTk.PhotoImage(img) #Canvasの用意 canvas = tkinter.Canvas(bg = "black", width=400, height=300) canvas.place(x=100, y=50) item = canvas.create_image(30, 30, image=img, anchor=tkinter.NW) #表示 root.mainloop()
方針としては、tkinterのメソッドからcanvasを用意して、その上にjpgイメージを載せる形で実現します。コード中に出てくるImageTkはjpgを扱いたい場合に使用します。
Step2 : 画像の切り替え
今回行いたいことは、Step1で作成した関数で表示した画像を自動で切り替えたいということです。しかし、上記コード中のroot.mainloopに入るとtkinterのgui上のbuttonなどのオブジェクトからしか制御を受け付けてくれなくなってしまうようでした。
実現したいのは、手動でbuttonを押すのではなく一定時間後に自動で切り替えたい、ということで、少々力業ではありますが、threadingライブラリを使用し、スレッドを立てる形で工夫しました。具体的には以下のコードで実現できました。
import sys import tkinter from PIL import Image, ImageTk import threading import time def show_image(): #外から触れるようにグローバル変数で定義 global item, canvas root = tkinter.Tk() root.title('test') root.geometry("400x300") img = Image.open('your_image.jpg') img = ImageTk.PhotoImage(img) canvas = tkinter.Canvas(bg = "black", width=400, height=300) canvas.place(x=100, y=50) item = canvas.create_image(30, 30, image=img, anchor=tkinter.NW) root.mainloop() #スレッドを立ててtkinterの画像表示を開始する thread1 = threading.Thread(target=show_image) thread1.start() #切り替えたい画像を定義 img2 = Image.open('your_image2.jpg') img2 = ImageTk.PhotoImage(img2) time.sleep(3) #3秒毎に切り替え #itemを差し替え canvas.itemconfig(item,image=img2) time.sleep(3) #itemをもとに戻す img = Image.open('your_image.jpg') img = ImageTk.PhotoImage(img) canvas.itemconfig(item,image=img)
canvasをグローバル変数で定義した上でスレッドを実行して画像を表示しておき、3秒経過したらcanvas内のjpsイメージを置き換え、また3秒経過したらもとの画像へ置き換え直す、という方式になっています。
まとめ
スマートなやり方かどうかはさておき、canvasをグローバルで定義してスレッドで実行しておき、そとからitemconfigで差し替えることで、一応やりたいことはできました。