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 なら可能らしいけど…。
[ ツッコむ ]
以上です。