- ベストアンサー
pythonで画像のサイズの再計算が関数で可能か
TkEasyGUIの使い方を試していて画像のサイズの問題で悩んでいます。 フォルダから画像ファイルのリスト化をして循環で表示させるまではどうにかなったのですが残念なことに表示範囲内で自動的に拡大縮小して表示する機能がないようにに見受けられ、サイズはデフォルトでてアスペクト比1:1に変換されて表示されます。画像ファイルによって比率が異なってるため4:3比の場合潰れてしまいます。恥ずかしなが前回の質問時全然そのことに気付きませんでした。今回下記コードのようにPillowを使って画像の大きさを取得しTkEasyGUIの画像のサイズを変更しようとしましたが、画像に合わせ動的に変更をする方が分かりません。画像に合わせ動的にサイズを変えるため関数を使えばと思ったのですが、関数をコピペで使ったことはあっても作ったことはありません。可能か否かも含めて何か方法がありましたらお教えください。 import TkEasyGUI as sg from PIL import Image import glob # GUIフォルダの画像ファイルを抽出 image_data = glob.glob('./GUI/*.png') # .pngのみを抽出 image_data.extend(glob.glob('./GUI/*.jpg')) # .jpgのみを抽出してリストに追加 # 画像のサイズを計算 im = Image.open(image_data[0]) h= im.size[1] w= im.size[0] h1=400 w1= int(w/(h/h1)) #sg.theme('alt') layout = [ [sg.Image(im,key="-image-",size=(w1,h1))], [sg.Button("◀"),sg.Button("□"),sg.Button("▶")] ] window = sg.Window('画像', layout) # イベントループ i=0 while True: event, values = window.read() if event == sg.WIN_CLOSED: break if event == "▶": i += 1 window["-image-"].update(image_data[i % len(image_data)]) elif event == "◀": i -= 1 window["-image-"].update(image_data[i % len(image_data)]) elif event == "□": i = 0 window["-image-"].update(image_data[i % len(image_data)]) window.close() なおDisvordで質問を試みていますが見学者が居ないのかどうか分かりませんが寂し状況に陥っていますので此処ではPillowを使った方法を考えて投稿させていただきました。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
何だろ。ウィンドウのサイズを変えたい、って事かしらん。 まず。 # ここから import glob # GUIフォルダの画像ファイルを抽出 image_data = glob.glob('./GUI/*.png') # .pngのみを抽出 image_data.extend(glob.glob('./GUI/*.jpg')) # .jpgのみを抽出してリストに追加 # ここまで 画像ファイルをpngとjpgに分けて抽出したい特殊な理由があるのかしら? ここはosモジュールを使って、次のように書いた方がシンプルだ。 # ここから import os # GUIフォルダの画像ファイルを抽出 dir_name = "GUI" image_data = [os.path.join(dir_name, file) for file in os.listdir(dir_name)] #ここまで これでGUIフォルダにある画像ファイルを一括で全部拾ってくれて、かつリスト化してくれる。 ・・・前回これ書いておけば良かったな。・・・こうしておけば、GUIフォルダに画像をどんなに追加しようとも、プログラム側で自動で面倒を見てくれる。 それで、だ。 > 関数をコピペで使ったことはあっても作ったことはありません。 これはアカンな。 これだけPythonを使ってるのなら、そろそろマジメにPythonを勉強すべきだ。 いや、誤解して欲しくないんだけど、 > コピペで使った これを批判してるわけじゃないんだ。むしろ正しい方針だ(笑)。 UNIX系プログラミングに於いては「既存のブツで使えるヤツは使う」ってのは正しい、んだよ。これに関しては貴方のやり方は大正解で、勘所を押さえている。 つまり、「コピペ万歳!」だ(笑)。人の作ったモノにタダ乗りするのは「UNIX系プログラミング」では推奨されるべき方針だ。 何でもかんでも自分で書けばイイ、ってモンじゃない。労力は最小限に押さえるべきだ。「車輪の再発明」はなるたけ避けるべきだ。 しかし、だな。コピペを「改造する」って前提だと、やはり「正しく改造する」コツは掴まなアカンのだよ。それには、やっぱりPythonを理解するしかないんだ。 教科書を挙げておく。これを読んでおけばいい。 世界標準MIT教科書 Python言語によるプログラミングイントロダクション 第3版: https://www.kindaikagaku.co.jp/book_list/detail/9784764906464/ これ一冊だけ、で当分間に合う筈だ。日本人が書いたヘンな日本のPython本より32,768倍くらいイイ本だ。 いずれにせよ、今のままだと、「何か問題が生じる度に」他人に頼ることとなる。また、これも誤解して欲しくないけど、貴方の「実践的な勉強法」が必ずしも悪い、とは言ってないが、今のままだと効率がいいんだか悪いんだか良く分からん勉強状態に陥ると思う。 いずれにせよ、一冊は「なんかキチンとまとまったプログラミングの書き方を指南する本」を手元に置いておくべきだと思う。 あるいは、PDFで次の文書を入手してプリントアウトしておいてもいい。 Think Python: https://cauldron.sakura.ne.jp/thinkpython/thinkpython/ThinkPython2.pdf なんかツマッた時はまずこのPDFの目次や索引から項目を引いてみよう。特に「関数の作り方」なんてのは基礎だ。畏れるに値しない。 さて、まずは次の部分を関数化する。 # 画像のサイズを計算 im = Image.open(image_data[0]) h= im.size[1] w= im.size[0] h1=400 w1= int(w/(h/h1)) これはこうなる。 # 画像のサイズを計算 def calc_size(im): return Image.open(im).size 基本的には与えられた画像をImage.openしたものからsizeを取ってきたらいい。結果、sizeがタプルなんで、この関数は画像サイズ(横・縦)のタプルを返す。 次はこれだ。 #sg.theme('alt') layout = [ [sg.Image(im,key="-image-",size=(w1,h1))], [sg.Button("◀"),sg.Button("□"),sg.Button("▶")] ] 動的にウィンドウサイズを変えたいのなら、レイアウト情報自体が動的に変わるように、つまり、関数化しておけばいい。 # sg.theme('alt') def theme(im): return [ [sg.Image(im, key='-image-', size=calc_size(im))], [sg.Button("◀"), sg.Button("□"), sg.Button("▶")] ] 引数から画像情報を受け取って、layoutが求めてるようなリストのリストを返すようにする。 それで、そもそもtcl/tkのウィンドウサイズは固定されてる、って前提だ。あんま画像サイズに従って伸び縮みする、って聞いたことがないんだよな・・・。 まぁ、少なくとも、TkEasyGUIのWindowの情報をマニュアル見て調べてみたんだけど、適した情報は見つからなかったわけだ。 TkEasyGUI Docs: https://github.com/kujirahand/tkeasygui-python/blob/main/docs/TkEasyGUI/widgets-py.md#Window そこで、だ。 今まではupdateメソッドでwindowを「更新」してたんだけど、それを止めて、ボタンをクリックする度にwindowを「閉じて」新しいwindowを生成する、ってのが結果貴方がやりたいことに一番近いんじゃないか、って思う。 コードは次のようになる・・・いわゆる「本格的な」Pythonプログラムの書き方に準じると全体的にはこうなる。 #!/usr/bin/env python3 import TkEasyGUI as sg from PIL import Image import sys, os # GUIフォルダの画像ファイルを抽出 dir_name = "GUI" image_data = [os.path.join(dir_name, file) for file in os.listdir(dir_name)] # 画像のサイズを計算 def calc_size(im): return Image.open(im).size # sg.theme('alt') def theme(im): return [ [sg.Image(im, key='-image-', size=calc_size(im))], [sg.Button("◀"), sg.Button("□"), sg.Button("▶")] ] if __name__ == '__main__': i = 0 window = sg.Window('画像', theme(image_data[i])) # イベントループ while True: event, values = window.read() if event == sg.WIN_CLOSED: window.close() sys.exit() if event == "▶": i += 1 elif event == "◀": i -= 1 elif event == "□": i = 0 i = i % len(image_data) window.close() window = sg.Window('画像', theme(image_data[i])) こんなカンジかな。
その他の回答 (5)
- cametan_42
- ベストアンサー率62% (162/261)
> 文字コードエンコードまでチェックしてもpngしかでないのでエディタに表示されている一覧を見てみるとjpgじゃなくJPGになっていた。 うん、まぁ、その可能性もあったよね。 取り敢えず「プログラムが正しい」のにも関わらず、上手く動かない場合、最初に疑うべきは確かに「データ」の方なんだ。・・・何故なら、プログラムよりデータ、あるいはデータ形式の方が重要だから、だ。 データ(写真)側の名称を変えたくない場合は、読み込まれるファイル名(文字列)をupperメソッドやlowerメソッドで弄ってから比較する方法もある。 >>> "hoge".upper() 'HOGE' >>> "HOGE".lower() 'hoge' > いままでこの違いで読み込めない経験したことが無かったのでびっくりしました。 フツーはそういうケースはほぼないんだけど、こういう事でしょ。 > powershellが混じる 正直、powershellは良く知らないんだけど、MS-DOS(あるいはその前身のCP/M)の仕様だと、文字列を含み、大文字・小文字の差がないのね。 例えば、MS-DOSだと、 "C:\Users\PCUSER" と "c:\users\pcuser" は全く同じ意味になる。 しかし、通常そんなのはあり得ない、んだ。 あるいは、SQLのデータベースなんかだと、やっぱり大文字・小文字の違いを無視してるケースが多いんだけど、やはりそれは「プログラミング言語」としては標準ではない。 ※: 「大文字・小文字を区別する」のをcase-sensitive、「大文字・小文字を区別しない」のをcase-insensitiveと呼称する。 プログラミング言語もそういう意味では二種類あって、文字列の中身まではそうじゃないが、例えば関数名などをmainとMAINを同じに扱うか、違う風に扱う言語、がある。C言語やPythonは後者のcase-sensitiveな言語、だ。 case-insensitiveな言語は、Pascal、BASIC、ANSI Common Lisp等がある。 なお、往年のPascal、あるいはBASICの教科書なんかだと、コードが全部大文字で書かれてたりするが、「大文字しか使えない」わけじゃなく、仕様上、単に「大文字と小文字を区別しない」だけで、当然全部小文字で記述可能だが、昔のパソコン等では、モニタの解像度が低く、結果、大文字「だけ」使った方が視認性が良かった、と言う情けない(笑)理由による。 結果、Pascal、Basic、ANSI Common Lisp等では当然大文字小文字混成でコードは書けるが、言語処理系に読み込まれた時点で、大文字・小文字の差は無くなるので、case-insensitiveな言語と違って、例えばmainとMAINは全く同じモノを指す事となる。 > プログラムは、何かと呪文を懸けるように出来ているように見えてきた・・・ まぁ、そろそろ腰を据えて、「プログラミングをキチンと学ぶ」段階に来てんじゃないの?って話だよね。 前述の教科書を購入して学習するか、pdf(Think Python)で「プログラミングを学ぶ」段階なんでしょ。もちろん、今の学習法を「やめろ」とは言ってないけど、ちょっと知識を補完した方が良い段階になってる、って事だ。 んで、「呪文をかける」って感じるのは、多分「逐次実行」がイマイチピンと来てない事に由来するんじゃないか、って思う・・・プログラミング初心者は「条件分岐」とか「反復」で躓く、って思われてるけど、実際は一番単純な「プログラムは書いた順に実行される」ってのを体感するのが結構難しい。ここがスッキリ分からないと、「コードの改変」(リファクタリング、と呼ぶ)が上手く行かないんだよ。 いずれにせよ繰り返すけど、一回腰を据えて勉強する段階なのかな。
お礼
有り難うございます。 >大文字・小文字の違いを無視してるケースが多いんだけど、やはりそれは「プログラミング言語」としては標準ではない。 いままでのPC生活で標準でない世界で使っていたのでせいぜいスペースやエスケープ文字で引っかかったことはありましたが。言語により大文字小文字だけ結構な事になっているのですね! 取りあえずBMPやTIFFは除き ".png",".jpg",".jpeg",".gif"の大小で対応することにします。 >コードの改変」(リファクタリング、と呼ぶ)が上手く行かない この現状の打破に相勤めます。
補足
画像表示部に保存イベントを加えたりして改変したものです。ファイルパスの指定画面に戻って再設定したかったが戻り方が分からなかったのでこんなコードになりました。 import TkEasyGUI as eg from PIL import Image import sys, os # set path SCRIPT_DIR = os.path.dirname(__file__) # 実行ファイルのパスを取得 SAVE_FILE = os.path.join(SCRIPT_DIR, "notepad-save-data.txt") # ウィンドウのレイアウトを定義 def main(): # ------------ メインウィンドウ作成 ------------ main_layout = [[eg.Frame( "画像ファイルパスの取得:", [ [eg.FilesBrowse(file_types=(("image Files", ".png",".jpg",".jpeg",".gif"),),target_key="-filepath-"),eg.Multiline("", key="-filepath-")], [eg.Button("Save"), eg.Button("default",pad=((10,1),(1,1))), eg.Button("next",background_color="green",pad=(10,1)),eg.Button("Exit",background_color="pink",pad=((170,1),(1,1)))], ])]] return eg.Window("メインウィンドウ", main_layout, finalize=True) window = main() # イベントループ while window.is_alive(): event, values = window.read() if event == "Exit": # exit button break # save button elif event == "Save": # notepad-save-data.txt に書き込む with open(SAVE_FILE, "w", encoding="utf-8") as f: f.write(f"{values['-filepath-']}") eg.popup("Saved") # open button elif event == "default": # notepad-save-data.txt が存在しているか if not os.path.exists(SAVE_FILE): continue # notepad-save-data.txt を読み込む with open(SAVE_FILE, "r", encoding="utf-8") as f: text = f.read() # 読み込んだテキストにアップデート window["-filepath-"].update(text) elif event == "next": image_list=f"{values['-filepath-']}" window.close() #image_data=[] image_data=image_list.split(";") image_data=list(image_data) # 画像のサイズを計算 def calc_size(im, h1 = 400): w, h = Image.open(im).size return (h1 * w // h, h1) def theme(im): return [ [eg.Image(im, key='-image-', size=calc_size(im))], [eg.Button("◀"), eg.Button("□"), eg.Button("▶"), eg.Button("保存",background_color="pink",pad=((50,1),(1,1)))] ] i = 0 window = eg.Window('画像', theme(image_data[i])) # イベントループ while True: event, values = window.read() if event == eg.WIN_CLOSED: window.close() sys.exit() elif event == "保存": with open(SAVE_FILE, "w", encoding="utf-8") as f: f.write(image_list) eg.popup("デフォルトが変更されます") window.close() sys.exit() elif event == "▶": i += 1 elif event == "◀": i -= 1 elif event == "□": i = 0 i = i % len(image_data) window.close() window = eg.Window('画像', theme(image_data[i]))
- cametan_42
- ベストアンサー率62% (162/261)
> ご指摘の部分を変えて試したところ image_data = [os.path.join(dir_name, file) for file in os.listdir(dir_name)\ if ".png" in file or ".jpg" in file] に問題があるのかpngファイルしか表示されません。 いや、問題は「理論的には」ない。 ちょっと次のようにして試して欲しい。 Pythonインタプリタで例えば、次のように打ってみると分かると思う。 >>> [file for file in ['frog2.png', 'a.jpg', 'b.jpg', 'notepad-save-data.txt'] if '.png' in file or '.jpg' in file] ['frog2.png', 'a.jpg', 'b.jpg'] 'notepad-save-data.txt'と言う文字列がフィルタリングされて含まれてないのが分かるだろう。 次にこうやってみる。 作業フォルダが今プログラムを書いてる場所だと仮定して、 >> [os.path.join("GUI", file) for file in os.listdir("GUI")] と走らせてみよう。 結果、GUIフォルダに入ってるファイルの文字列のリストが返ってきたら成功だ。 次にこうしてみる。 >>> [os.path.join("GUI", file) for file in os.listdir("GUI") if ".png" in file or ".jpg" in file] 仮にこの状態で、pngしか返ってこず、jpgが含まれたリストが返ってこない、としたら残念ながらおそらく例によって文字コードの問題だろう。 Python2時代に比べてPython3だとマシになったが、たまに文字コードのデコードの問題が出てくる。 jpg拡張子前提の画像ファイルが、まずはキチンと名前が付けられてるかどうか確認して、それでも上手く動かない、となったら恐らく文字コードの問題だ。 このようにして、 >> [os.path.join("GUI", file) for file in os.listdir("GUI") if ".png" in file or ".jpg".encode("shift_jis") in file.encode('utf-8')] # 最後でfileを確実にUTF-8の文字列へと変更し比較する これで与えられるリストに*.jpgが含まれるようになるか確認しよう。 僕はLinuxユーザーなんで、Windowsでどうなるかは分からないけどね。 注: 現代の主要なLinuxディストリビューションだとほぼ全般的に文字コードとしてはUTF-8が普及してる。 一方、Windowsだと、内部的には既にUTF-8だが、日本語だと表面的にいまだShift-JISが混ざってる、あるいは変換してる、って状態な為、Pythonみたいな「文字コード変換」がイマイチ信頼ならない言語だと更に問題がややこしくなってるんだ。 ぶっちゃけ、Linuxだと文字コードの面倒は、ほぼ起こらないんだ。 > 最初のwindowをそのまま残したままになってしまう残念な方法ですが・・・ そりゃ、window.close()を書き忘れてるから、でしょう。 それと、だ。 イベントループみたいな「実行部分」は常にif __name__ == '__main__':の後に置くように。そこが、スクリプトで常に最初に実行される部分で、C言語なんかのmain関数みたいなモノ、って覚えておけばいい。 注: 厳密にはこれは違って、if __name__ == '__main__':があろうがなかろうが、Pythonは書かれた全てを実行する。 実はif __name__ == '__main__':の目的は逆で、書いたプログラムが「他のPythonプログラムから」モジュールとして呼び出された時に、if __name__ == '__main__':以降の「実行をスキップする」ようになってる、って言った方が正しい。 が、Pythonプログラミングの書法だと、一般的には「問答無用で実行される」関数やデータ型の定義以外、つまり「イベントループ」的なモノは、いずれにせよ、if __name__ == '__main__':以降に置く、ってのがお約束となっている。
お礼
再々の回答有り難うございます。 文字コードエンコードまでチェックしてもpngしかでないのでエディタに表示されている一覧を見てみるとjpgじゃなくJPGになっていた。 [os.path.join("GUI", file) for file in os.listdir("GUI") if ".png" in file or ".JPG" in file] いままでこの違いで読み込めない経験したことが無かったのでびっくりしました。 image_list=f"{values['-filepath-']}" window.close() 最初のwindowsが消えました。 プログラムは、何かと呪文を懸けるように出来ているように見えてきた・・・ 何かとお世話になりました。
- cametan_42
- ベストアンサー率62% (162/261)
> GUIフォルダに画像ファイル以外がある そういう時はフィルタリングするんだ。 # GUIフォルダの画像ファイルを抽出 dir_name = "GUI" image_data = [os.path.join(dir_name, file) for file in os.listdir(dir_name)\ if ".png" in file or ".jpg" in file] Pythonの最重要構文はリスト内包表記、だ。リスト内包表記を使いこなそう。 じゃないとPython初心者は脱却出来ない。 5.1.3. リストの内包表記: https://docs.python.org/ja/3/tutorial/datastructures.html#list-comprehensions # 画像のサイズを計算 def calc_size(im): im = Image.open(im) h= im.size[1] w= im.size[0] h1=400 return (int(w/(h/h1)),h1) ここはこう書いた方がいい。 # 画像のサイズを計算 def calc_size(im, h1 = 400): # マジックナンバーを使うならキーワード引数を活用しよう w, h = Image.open(im).size # 構造化代入 return (h1 * w // h, h1) # 商を求めるなら // を使う 高さを完全に400と想定してるのか、あるいは他の数値に変える可能性があるのか。 あまりにも明示的に変数を使って「定数」的に数をソースコードの中に埋め込むと、それらは「マジックナンバー」と呼ばれる。仮にソースコードを修正する、って事になったらあっちこっちにとっ散らかった数を修正せなアカン。 こういう場合、Pythonではキーワード引数を使って「デフォルト値」を設定するのが上手いやり方だ。 4.9.2. キーワード引数: https://docs.python.org/ja/3/tutorial/controlflow.html#keyword-arguments 次に、タプルを返すような呼び出し、 Image.open(im).size に対して、こういう書き方 h= im.size[1] w= im.size[0] は冗長だ。 Pythonではこう一行で書ける。 w, h = Image.open(im).size こういうのを、一般的には「構造化代入」と呼び、Pythonでは特に「アンパック代入」と呼ばれる。 Pythonでタプルやリストをアンパック(複数の変数に展開して代入): https://note.nkmk.me/python-tuple-list-unpack/ > (int(w/(h/h1)),h1) 別に間違いじゃないけど、単に「商」が欲しい時には演算記号としては//を使う。 整数除算: https://docs.python.org/ja/3/glossary.html#term-floor-division
お礼
早速有り難うございます。 ご指摘の部分を変えて試したところ image_data = [os.path.join(dir_name, file) for file in os.listdir(dir_name)\ if ".png" in file or ".jpg" in file] に問題があるのかpngファイルしか表示されません。 うろ覚えのjavascriptやpowershellが混じる中途半端な似非知識で感でやっているようなコード書き申し訳ありません。
補足
フォルダ内の画像ファイル全てをリスト化しないで任意の画像ファイルのみ選択しリスト化する方法と教えてもらったコードを合体させたみたが、最初のwindowをそのまま残したままになってしまう残念な方法ですが・・・ import TkEasyGUI as eg from PIL import Image import sys, os # set path SCRIPT_DIR = os.path.dirname(__file__) # 実行ファイルのパスを取得 SAVE_FILE = os.path.join(SCRIPT_DIR, "notepad-save-data.txt") # ウィンドウのレイアウトを定義 layout = [ [eg.Frame( "画像ファイルパスの取得:", [ [eg.FilesBrowse(file_types=(("image Files", ".png",".jpg"),),target_key="-filepath-"),eg.Multiline("", key="-filepath-")], [eg.Button("Save"), eg.Button("default",pad=((10,1),(1,1))), eg.Button("next",background_color="green",pad=(10,1)),eg.Button("Exit",background_color="pink",pad=((170,1),(1,1)))], ])]] window = eg.Window("Notepad", layout=layout,size=(400,200)) # イベントループ while window.is_alive(): event, values = window.read() if event == "Exit": # exit button break # save button elif event == "Save": # notepad-save-data.txt に書き込む with open(SAVE_FILE, "w", encoding="utf-8") as f: f.write(f"{values['-filepath-']}") eg.popup("Saved") # open button elif event == "default": # notepad-save-data.txt が存在しているか if not os.path.exists(SAVE_FILE): continue # notepad-save-data.txt を読み込む with open(SAVE_FILE, "r", encoding="utf-8") as f: text = f.read() # 読み込んだテキストにアップデート window["-filepath-"].update(text) elif event == "next": image_list=f"{values['-filepath-']}" break #image_data=[] image_data=image_list.split(";") image_data=list(image_data) eg.theme('alt') # 画像のサイズを計算 def calc_size(im, h1 = 400): w, h = Image.open(im).size return (h1 * w // h, h1) # eg.theme('alt') def theme(im): return [ [eg.Image(im, key='-image-', size=calc_size(im))], [eg.Button("◀"), eg.Button("□"), eg.Button("▶")] ] if __name__ == '__main__': i = 0 window = eg.Window('画像', theme(image_data[i])) # イベントループ while True: event, values = window.read() if event == eg.WIN_CLOSED: window.close() sys.exit() if event == "▶": i += 1 elif event == "◀": i -= 1 elif event == "□": i = 0 i = i % len(image_data) window.close() window = eg.Window('画像', theme(image_data[i]))
- cametan_42
- ベストアンサー率62% (162/261)
なお、もう一つ言っておこう。 僕とかの観点だと、TkEasyGUIは大してEasyでもないんだよ(笑)。 いや、確かに煩雑になりかねないGUIの大量のコードを「書かなアカン」事に対しては物凄く短くコードが書けるようになってる。 ただし、だ。実はもっと本音言うと、そもそも「GUIのコードを書きたくねぇ」んだよな(笑)。 つまり(僕を含めた)そういった人たちはそもそも「GUIのコードを書かない」。じゃあどうするか、ってぇとGUIビルダってソフトを使うんだよ(笑)。ウィンドウにマウスでペタペタと「部品」を貼っつけていく・・・。それでGUIのガワは「出来上がり」となるわけ。 どう考えてもそっちの方がラクなんだよな(笑)。GUIのコードと直接格闘する必要がないし。 ただ、Pythonのtcl/tkラッパー、tkinterに良いGUIビルダーが無い、んだ。そもそも、tcl/tk自体が「簡単にGUIのコードを書ける」って前提だった為、GUIビルダーの発展がクッソ遅かったのね。 結果、tkinterのGUIビルダーはバギーなモノしかなく、その間隙を突いてTkEasyGUIが出てきたように見える。 そんなわけで、tcl/tkは枯れてて安定してるんだけど、PythonでGUIのデスクトップアプリを作ろう、ってヤツはtkinterは使わないんだ。 おそらく一番使われてるのはwxPythonじゃないか、って思う。 wxPython: https://wxpython.org これもクロスプラットフォームなGUI ツールキットで、ベースとなってるのはwxWidgetsと言うライブラリだ。 wxWidgets: https://wxwidgets.org/ で、重要なのは、「コードを書かない」。つまりwxPython用のGUIビルダがある。 wxGlade: https://wxglade.sourceforge.net 古い記事だけど、使い方はこの記事が良くまとまっている。見た目が変わってるけどやれる事は同じだ。 wxWidgets でクロスプラットフォーム GUIアプリを作ろう: http://0xcc.net/pub/uu-2004-08/ 繰り返すけど、「GUIビルダーがある」からwxPythonを使う、って言って過言ではない状況だ。また、同種のツールにQtってのもあるけど、wxの方が結果、Qtよりややこしくない・・・ってなわけでPython + wxPythonで制作されたGUIアプリが多いわけだ。 まぁ、どうしてもTkEasyGUIにこだわりたい、ってのならそれはそれでいいけど、なかなかユーザーが少ないんで、やっぱ回答が付かなくなるんじゃないかな、って事だ。
お礼
すみません、pythonを最初雑誌の連載記事を見て始めたときモジュールとしてtkinterを勧められていて使っていて結構面倒なのでPySimpleGUIに手を出したが大してものにならず、PySimpleGUIの商用化云々でTkEasyGUIに乗り換えてみようと年寄りの暇つぶしで再挑戦していたところです。wxPython用のGUIビルダがあるなんてネットのお勧めでに載っていなかったような・・ただ単に見えなかっただけかも
- chie65536(@chie65535)
- ベストアンサー率44% (8740/19838)
アスペクト比を保ったまま、横を400以下、縦を300以下にするなら h1=400 w1= int(w/(h/h1)) の部分を if (h*4) > (w*3) h1=300 w1= int((w*h1)/h) else w1=400 h1= int((h*w1)/w) のようにします。 やってる事は「横4縦3の4:3の画像にくらべ、縦長か、横長か」を判定して、縦基準で計算するか、横基準で計算するか、切り替えているだけです。
お礼
chie65536様 解答有り難うございます。 残念ながら質問趣旨がよく伝わっていないみたいですね? リストに各々のアスペクト比が209:720,1:1,4:3の3ファイルのパスがあるとして最初に im = Image.open(image_data[0]) のためアスペクト比が209:720に固定されてしまい後からイベントで [sg.Image(im,key="-image-",size=(w1,h1))], の"-image-"部分を1:1等の画像に変更してもsize=(w1,h1))は209:720を維持したままなので この部分をsize=(400,400)等の画像のアスペクト比を反映した値に変えたいと思っています。
お礼
cametan_42様 有り難うございます。 最初の回答のあったコードそのままコピペして動かすとディスプレイをはみ出す大きな画像が表示されてしまいました。そのままの画像情報でなくh1=400のように基準値を設け変換し表示することは出来ないでしょうか。コードの詳しことはさておきよろしくお願いします。
補足
# GUIフォルダの画像ファイルを抽出 GUIフォルダに画像ファイル以外があるため dir_name = "GUI" image_data = [os.path.join(dir_name, file) for file in os.listdir(dir_name)] をglobを使い下記コードに書き変えました image_data = glob.glob('./GUI/*.png') # .pngのみを抽出 image_data.extend(glob.glob('./GUI/*.jpg')) # .jpgのみを抽出してリストに追加 # 画像のサイズを計算 def calc_size(im): im = Image.open(im) h= im.size[1] w= im.size[0] h1=400 return (int(w/(h/h1)),h1) なんとか循環表示が出来たのですが、なんかいまいちだな やはり表示フレームを作りその中にアスペクト比を維持しながら拡大縮小する方法の方が普段使っているDB上で画像表示させるときに慣れているのでしっくりと来る。