2020/03/04(水) [n年前の日記]
#1 [python] PySimpleGUIを使って画像表示
せっかく Python + PySimpleGUI を触ったことだし、せめて画像表示できるところまで試してみようかと。
環境は、Windows10 x64 1909 + Python 3.7.6 32bit + PySimpleGUI 4.16.0 + Pillow 7.0.0。
_PySimpleGUI/DemoPrograms の中に、 _PySimpleGUI/Demo_Img_Viewer.py というデモスクリプトがあるのでソレを参考に。件のスクリプトは、指定したフォルダ内の画像ファイルをリスト表示して、選択すると画像を表示するスクリプトだけど、自分の場合は単に画像ファイルを1ファイル指定して表示するようにしてみたり。
こんな感じになった。
環境は、Windows10 x64 1909 + Python 3.7.6 32bit + PySimpleGUI 4.16.0 + Pillow 7.0.0。
_PySimpleGUI/DemoPrograms の中に、 _PySimpleGUI/Demo_Img_Viewer.py というデモスクリプトがあるのでソレを参考に。件のスクリプトは、指定したフォルダ内の画像ファイルをリスト表示して、選択すると画像を表示するスクリプトだけど、自分の場合は単に画像ファイルを1ファイル指定して表示するようにしてみたり。
こんな感じになった。
◎ ソース。 :
_myimgviewer.py
以下で実行。
ハマったところは、ファイル選択処理部分。FileBrowse というエレメント(?)を用意すれば、ウインドウ上では「Browse」というボタンが表示されて、そのボタンをクリックするとファイル選択ができるのだけど。その選択されたファイルパスをどうやって取得するのかが分からなくて。
ひたすらググってみた感じでは、イベントループ内で、values[] の中にファイルパスが入ってくる瞬間が、ファイル選択された時、みたいな感じで…。
ということで、FileBrowse() を用意する際に key='-FILENAME-' を指定しておいて、後に、イベントループの中で、values['-FILENAME-'] の中身が空じゃないかチェックして、空じゃなければ画像ファイルが選択された時だから画像ファイルを読み込んで更新、てな感じに。
とりあえず、PySimpleGUI を使って画像表示はできたから、画像を読み込んで何か処理をして結果をプレビュー、といったスクリプトなら書けそうかなと…。
本当は、エクスプローラ等からD&D(ドラッグアンドドロップ)してファイルを開けたらいいのだけれど。tkinter にそんな機能は無いので、それはちょっと無理っぽい。tkinter を使う PySimpleGUI ではなく、おそらくは Qt を使う PySimpleGUIQt なら可能らしいけど…。
import PySimpleGUI as sg
from PIL import Image, ImageTk
import io
import sys
# import os
img_types = (".png", ".jpg", "jpeg", ".tiff", ".bmp")
status_text = ''
fname = None
if not len(sys.argv) == 1:
fname = sys.argv[1]
if fname:
if not fname.lower().endswith(img_types):
sg.popup("Cancel", fname + " is Not image file")
raise SystemExit("Canceling: Not image file")
def get_img_data(f, maxsize=(1200, 850), first=False):
"""Generate image data using PIL."""
global status_text
im = Image.open(f)
status_text = "%d x %d" % im.size # original image size
im.thumbnail(maxsize)
status_text += " (%d x %d)" % im.size # thumbnail image size
if first:
bio = io.BytesIO()
im.save(bio, format="PNG")
del im
return bio.getvalue()
return ImageTk.PhotoImage(im)
# layout
firstfg = True
if fname:
image_elem = sg.Image(data=get_img_data(fname, first=firstfg))
fname_elem = sg.InputText(size=(80, 1), enable_events=True,
default_text=fname)
firstfg = False
else:
image_elem = sg.Image()
fname_elem = sg.InputText(size=(80, 1), enable_events=True)
status_elem = sg.Text(key='-STATUS-', size=(64, 1))
layout = [
[fname_elem, sg.FileBrowse(key='-FILENAME-')],
[status_elem],
[image_elem]
]
# create window
window = sg.Window('Image Viewer', layout, return_keyboard_events=True,
location=(0, 0), use_default_focus=False)
# event loop
while True:
event, values = window.read()
if event in (None, 'Exit'):
break
if values['-FILENAME-'] != '':
# filename select
fname = values['-FILENAME-']
if fname.lower().endswith(img_types):
# load image
image_elem.update(data=get_img_data(fname, first=firstfg))
fname_elem.update(fname)
status_elem.update(status_text)
firstfg = False
window.close()
以下で実行。
python myimgviewer.py or python myimgviewer.py hoge.png
ハマったところは、ファイル選択処理部分。FileBrowse というエレメント(?)を用意すれば、ウインドウ上では「Browse」というボタンが表示されて、そのボタンをクリックするとファイル選択ができるのだけど。その選択されたファイルパスをどうやって取得するのかが分からなくて。
ひたすらググってみた感じでは、イベントループ内で、values[] の中にファイルパスが入ってくる瞬間が、ファイル選択された時、みたいな感じで…。
ということで、FileBrowse() を用意する際に key='-FILENAME-' を指定しておいて、後に、イベントループの中で、values['-FILENAME-'] の中身が空じゃないかチェックして、空じゃなければ画像ファイルが選択された時だから画像ファイルを読み込んで更新、てな感じに。
とりあえず、PySimpleGUI を使って画像表示はできたから、画像を読み込んで何か処理をして結果をプレビュー、といったスクリプトなら書けそうかなと…。
本当は、エクスプローラ等からD&D(ドラッグアンドドロップ)してファイルを開けたらいいのだけれど。tkinter にそんな機能は無いので、それはちょっと無理っぽい。tkinter を使う PySimpleGUI ではなく、おそらくは Qt を使う PySimpleGUIQt なら可能らしいけど…。
[ ツッコむ ]
以上です。
