• ベストアンサー

pythonでelifが多数の時の対処方法について

お世話になっています。 pythonのTkEasyGUIを使い画像表示の方法を試しています。下記の簡単なコードではボタンクリックで画像が順に変わるだけのものですが、同じボタンで処理したいためelifを使い条件分岐をさせて変えるようにしていますが、今回の場合のように3枚程度の画像の場合問題がないのですが、これでは枚数が増える都度コードを追加することになります。インデックス部分の処理だけで変化させることは出来ないでしょうか。 import TkEasyGUI as sg image_data =['GUI/frog2.png','GUI/a.jpg','GUI/b.jpg'] sg.theme('alt') layout = [ [sg.Image(image_data[0],key="-image-")], [sg.Button("image1")] ] window = sg.Window('画像', layout=layout) i=0 # イベントループ while True: event, values = window.read() if event == sg.WIN_CLOSED: break if event == "image1" and i==0: i=i + 1 window["-image-"].update(image_data[i]) elif event == "image1" and i==1: i=i + 1 window["-image-"].update(image_data[i]) elif event == "image1" and i==2: i=i - 2 window["-image-"].update(image_data[i]) window.close() 今回、Discord > TkEasyGUIへ投稿しようとも考えてアカウントの登録までしましたがスマホも使えない年寄りはそこで固まってしまいました。TkEasyGUI特有の問題かpythonの一般問題かどうか分かりませんがよろしくお願いいたします。

質問者が選んだベストアンサー

  • ベストアンサー
回答No.1

まずは、 > 今回、Discord > TkEasyGUIへ投稿しようとも考えてアカウントの登録までしましたがスマホも使えない年寄りはそこで固まってしまいました。 DiscordってのはOKWAVE/教えて!goo/Yahoo!知恵袋みたいな「Q&Aサイト」を構築するプログラムなのね。ソフトウェア名称でいうと、知ってるかは知らんが、Stack Exchangeってプログラムに近い。最近イケてる「Q&Aコーナー」で使われてるソフトウェアで、言っちゃえば掲示板のもっとスタイリッシュなソフトウェアなんだ。 Discord: https://ja.wikipedia.org/wiki/Discord 確か、Python公式のQ&AフォーラムもDiscordを採用してると思う。 Pythonフォーラム(公式): https://python-forum.io 使い方は単に、質問スレッドを立ち上げて、そこに回答者が回答を書いていく・・・要はOKWAVEと殆ど同じ、だ。 見た目で緊張してるだけ、でやってること/やるべきこと、ってのは殆ど変わんないと思う。 > TkEasyGUI特有の問題かpythonの一般問題かどうか分かりません 結論から言うと「一般問題」ではある。 でもやっぱ「あまり答えたくない」問題に分類されるんだよ(笑)。外部ライブラリ使用、ってのはそういうことなの。 回答者側の立場から言うと、だ。「マトモな回答者」なら、貴方の提示コードを「まずはキチンと動かそう」とする。 ところが、TkEasyGUIとか「自分が使うかどうか分からない」ライブラリをインストールせなアカン。もうそれだけで「自分のPCのストレージを汚す」んで、やっぱやりたくねぇんだよ(笑)。 これは、いつぞやのMySQLの質問でもそうなんだけど、質問に答えるだけで、場合によってはMySQLみたいな「デカいソフトウェア」を自分のPCにインストールせなアカンわけじゃん?これは相当億劫なの(笑)。ユーザー名設定したりパスワード設定したり、「質問に答えるだけで」やんなきゃなんないじゃん。面倒なんだよね。 あるいは自分で既にMySQLを使ってる場合、そういうのを「質問に答えるだけで」汚さなアカンわけじゃん?大体それで躊躇するんだよ。「そこまでしたくねぇよな」ってなる。 だからそういう「外部ライブラリ専用Q&Aサイト」を訪問した方がエエよ、って言ったわけだ。 ※: ちなみにこれが「SQLiteを使った」質問だったらちょっと敷居が下がったかも・・・いずれにせよ「MySQL」ってのが本格的過ぎて、「気軽に答える」には大げさ過ぎるんだ。 また、Pythonistaなら、恐らく外部ライブラリである「SQLAlchemyを使え」と言った答えになり、そっちのQ&Aサイトに誘導する、って話になったかも。 SQLite: https://www.sqlite.org/index.html SQLAlchemy: https://www.sqlalchemy.org/ 他にも問題がある。 貴方のコードには、 image_data =['GUI/frog2.png','GUI/a.jpg','GUI/b.jpg'] と書いてるけど、frog2.pngとかa.jpg、b.jpgが何なのか、コッチ側にはサッパリ分からんのだ。 いや、拡張子見れば画像データだ、ってことは分かるんだけど、コッチ側では「再現」出来ないわけじゃん?言い換えると貴方の提示コードは貴方の環境への「依存度」が極めて高い、わけだね。 これは「一般想定の」回答者側には結構困る質問なんだよ(笑)。これはNumpyみたいな有名な外部ライブラリでも同じでさ。基本的には回答者が「同じライブラリを用いてる」とか?偶然性が無いとあまり答えられない質問になっちゃうんだ。 こういう「一般的な」Q&Aサイトでのプログラミングに関する質問では・・・いや、それに限らないんだろうけど、質問者のプログラムは「再現性」が無いとどうしようもないことがままあるんだ。例えば今回の質問だと、プログラムを置いてるフォルダの同階層にGUIと名付けられたフォルダがあって、そこに画像が入ってる、って辺りまで読めないとならない。そしてそういう「環境」を再構成するのが、言っちゃえば面倒臭いんだよ(笑)。 不真面目な回答者だったらコードを読んだだけ、で何かテキトーな事を言う、なんつー事もあり得るんだけど、そうじゃない場合、「再現」するのが面倒臭いってのは、かなり回答率を下げる事になっちゃうんだ。 そういうのもあって、「そのライブラリ専門の」Q&Aコーナーに投げた方がいいよ、って言ってるわけだ(当然そこに集ってる奴らは同じライブラリを使ってるから)。 > インデックス部分の処理だけで変化させることは出来ないでしょうか。 貴方がやりたい事は、コンピュータ・サイエンス的には「循環リスト」(Circular List)と言うモノを使えば解決する問題だ。 「データ構造とアルゴリズム」ってのを勉強した事があるのかどうかは知らないけど、いわゆる「線形片方向連結リスト」で、リストの末尾がNULLを指さず、そのリストの先頭を指してる、って場合、インデックスiがどれだけ増えてもそのリストをグルグル回る、って事になる。 そういうデータ構造があれば解決しちゃうんだ。 一方、Pythonにはそういう循環リスト、ってデータ型が無い。もっと言っちゃうと、Pythonのリストは実は「線形片方向連結リスト」ではない。 そこでPythonでは、循環リストをエミュレートするには次のようなトリックを用いる。 >>> image_data =['GUI/frog2.png','GUI/a.jpg','GUI/b.jpg'] >>> 0 % len(image_data) 0 >>> 1 % len(image_data) 1 >>> 2 % len(image_data) 2 >>> 3 % len(image_data) 0 >>> 4 % len(image_data) 1 >>> 5 % len(image_data) 2 >>> 6 % len(image_data) 0 上を見れば分かるだろうけど、割られる方の数をどんなに増やしても、リスト(image_data)の大きさ(あるいは長さ)との剰余計算を用いる限り、リストの長さを超える数は返ってこない・・・言い換えると、このケースでは、0、1、2の3つが順繰りに返ってくるだけ、となる。 これが貴方がしたかった事だ。 すなわち、イベントループ部分を、 # イベントループ while True: event, values = window.read() if event == sg.WIN_CLOSED: break else: i += 1 window["-image-"].update(image_data[i % len(image_data)]) と書けば終了、だ。 そうすれば、image1ボタンをクリックすると3つの画像が順繰りに、かつ永遠に表示される事、となる。 以上。

turu575
質問者

お礼

cametan_42様、有り難うございます。 >Pythonでは、循環リストをエミュレートするには次のようなトリックを用いる。 たったこれだけでいいのですね!・・・他のサイトで見たことがある方法では、もっと面倒なことになっていてどう適用していいか解りませんでした。 あと、面倒臭い質問になるグタグタの言い訳として、基本、プログラムの勉強は皆無に近い、ただ興味を持った部分だけコピペを主体でコードを書き動かしているだけ、例えば前の質問でMysqlへの接続していたけどそのMysqlも昔SQLの勉強と100万以上のデータのクロス集計等を目的でただ入れただけでたまにバージョンアップはしているが最新版でないし、データはテスト用のものが主です。普段は別の慣れ親しんだDBを使用(pythonで接続モジュールは大昔にあったきり)とExcelで間に合っているので、かなり狭い使い方に限られているので質問能力も育たないため等々・・・ 様々なご指摘有り難うございます。なお、Discord > TkEasyGUIへの投稿は諦めていません、Windowとtableの背景色の設定方法が分からないので。

その他の回答 (2)

  • retorofan
  • ベストアンサー率34% (435/1276)
回答No.3

>elifを使い条件分岐をさせて変えるようにしています あなたのコードは、いわゆる「スパゲティコード」と称される記法で、 しかも、「i==0、i==1、i==2」のようにマジックナンバーを含んでいて 決して宜しいとはいえません。 変数「image_data」から画像枚数がわかりますから、 それを利用して、定数を使わずにコードを組むことができます。 [サンプルコード] import TkEasyGUI as sg image_data = ['GUI/frog2.png', 'GUI/a.jpg', 'GUI/b.jpg'] sg.theme('alt') layout = [ [sg.Image(image_data[0], key="-image-")], [sg.Button("Next Image")] ] window = sg.Window('画像', layout=layout) current_image_index = 0 def update_image(index): window["-image-"].update(image_data[index]) # イベントループ while True: event, values = window.read() if event == sg.WIN_CLOSED: break if event == "Next Image": current_image_index = (current_image_index + 1) % len(image_data) update_image(current_image_index) window.close() 以上のコードは、 image_dataの長さを使ってインデックスを循環させています。 こうすれば、画像数が増減してもコードを変更する必要がなくなり、 より柔軟で保守しやすいコードになります。

turu575
質問者

お礼

retorofan 様 有り難うございます。 前に他のサイトで見たtkinterでインデックスを循環させている方法がありましたが、どう適用していいか解りませんでしたが、こうすればいいのですね参考にさせていただきます。

回答No.2

if event == "image1" and i==0: i=i + 1 window["-image-"].update(image_data[i]) elif event == "image1" and i==1: i=i + 1 window["-image-"].update(image_data[i]) elif event == "image1" and i==2: i=i - 2 window["-image-"].update(image_data[i]) は、まったくの無駄です。 eventの値がimage1だったら、iが幾つであっても、やる事は同じです。 無駄なif文は以下の1つにまとめられます。 if event == "image1": i = 0 if i == ● else i + 1 window["-image-"].update(image_data[i]) ●の部分は「枚数ー1」にします。3枚だったら●は「2」です。 image_dataに10枚分用意したなら、●は9にします。 image_dataに100枚分用意したなら、●は99にします。 枚数を変えたい場合は●の数値を変えるだけです。

turu575
質問者

お礼

chie65536(@chie65535)様、有り難うございます。 window = sg.Window('画像', layout=layout) i = 0 # イベントループ while True: event, values = window.read() if event == sg.WIN_CLOSED: break if event == "image1": i = 0 if i == len(image_data)-1 else i + 1 window["-image-"].update(image_data[i]) window.close() で出来ました。

関連するQ&A