🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
ウィンドウ

コンピューター用語において、ウィンドウとはユーザとプログラムのやり取りを可能にするGUIの枠組みのことをいいます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

PyCharm

エディター・開発ツール

Q&A

1回答

2406閲覧

終了ボタンをクリックしたのに処理が続く

_N_M_

総合スコア1

ウィンドウ

コンピューター用語において、ウィンドウとはユーザとプログラムのやり取りを可能にするGUIの枠組みのことをいいます。

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

PyCharm

エディター・開発ツール

0グッド

1クリップ

投稿2021/01/22 05:48

システム概要

メインメニューの顔認証ボタンをクリックすると、比較用画像(face.jpg)とimageフォルダ内のjpg画像全てを読み込み、特徴量が最も0に近い画像にTrueの判定がされ、終了ボタンをクリックすると判定結果を表示するシステムとなっています。
終了ボタンを処理中にクリックすることはできません。

python

1import PySimpleGUI as sg 2import matplotlib.pyplot as plt 3from glob import glob 4import face_recognition 5 6#メインメニュー 7layout1 = [ 8 [sg.Text('メインメニュー',size=(27,2), font=(100) ,justification='center')], 9 [sg.Button('顔認証',size=(15,3)),sg.Button('終了',size=(15,3),)], 10] 11 12window = sg.Window('face_checker', layout1) 13 14 15while True: 16 event, values = window.read() 17 18 if event == '終了' or event == sg.WIN_CLOSED or event == '' : 19 break 20 21 elif event == '顔認証': 22 23 # 保存されている人物の顔の画像を読み込む。 24 known_face_imgs = [] 25 for path in glob('image/*.jpg'): 26 img = face_recognition.load_image_file(path) 27 known_face_imgs.append(img) 28 29 # 認証する人物の顔の画像を読み込む。 30 face_img_to_check = face_recognition.load_image_file("face.jpg") 31 32 # 顔の画像から顔の領域を検出する。 33 known_face_locs = [] 34 for img in known_face_imgs: 35 loc = face_recognition.face_locations(img, model="cnn") 36 known_face_locs.append(loc) 37 38 face_loc_to_check = face_recognition.face_locations(face_img_to_check, model="cnn") 39 40 41 def draw_face_locations(img, locations): 42 fig, ax = plt.subplots() 43 ax.imshow(img) 44 ax.set_axis_off() 45 for i, (top, right, bottom, left) in enumerate(locations): 46 # 長方形を描画する。 47 w, h = right - left, bottom - top 48 ax.add_patch(plt.Rectangle((left, top), w, h, ec="r", lw=2, fill=None)) 49 plt.show() 50 51 52 for img, loc in zip(known_face_imgs, known_face_locs): 53 draw_face_locations(img, loc) 54 draw_face_locations(face_img_to_check, face_loc_to_check) 55 56 # 顔の領域から特徴量を抽出する。 57 known_face_encodings = [] 58 for img, loc in zip(known_face_imgs, known_face_locs): 59 (encoding,) = face_recognition.face_encodings(img, loc) 60 known_face_encodings.append(encoding) 61 62 (face_encoding_to_check,) = face_recognition.face_encodings( 63 face_img_to_check, face_loc_to_check 64 ) 65 66 matches = face_recognition.compare_faces(known_face_encodings, face_encoding_to_check) 67 print(matches) 68 69 # 特徴点 70 dists = face_recognition.face_distance(known_face_encodings, face_encoding_to_check) 71 print(dists) 72 print(min(dists)) 73 74 # 画像ファイル一覧 75 for show in glob("image/*"): 76 print(show) 77 break 78 79print("自動的に終了します") 80window.close()

発生している問題・エラーメッセージ

imageフォルダ内の画像を読み込むと、画像が一枚ずつ表示されるはずでしたが、一枚目以降が表示されませんでした。その際にクリックできないはずの終了ボタンがクリックできるようになっていました。クリックしてみると、処理が終わらず何故か二枚目が表示され、それ以降も同じ手順で表示できました。
なお、全ての画像が表示された後に終了ボタンをクリックした際には、正常な判定結果が表示されて終了しました。

補足情報

OS:Windows10
Pythonのバージョン:Python3.8.5
開発環境:PyCharm Community Edition 2020.2.4 x64

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

終了ボタンを処理中にクリックすることはできません。

問題点: イベントループの競合

python

1# PySimpleGUI のイベントループ 2while True: 3 4 event, values = window.read() 5 ...

PySimpleGUI の GUI は window.read() 内部で
GUI の応答処理をして、ユーザーから何かアクションがあった場合に
event, values に値を返します。

GUI プログラムを応答可能にするには、
window.read() が定期的に呼ばれる必要があります。

このようなGUI等のイベント駆動のプログラムに置いては、
イベントループ内でループの実行を妨げるブロッキング操作をしてはいけません。
(time.sleep, 時間の掛かるループ, plt.show が該当します)

問題になる箇所は

python

1# pyplot のイベントループ 2 3plt.show() # <-- ここでコードの実行が待機状態になる 4 5# plt.show のウィンドウが閉じるまで以降のコードは実行されない 6# --> PySimpleGUI のウィンドウは応答なし状態になる。

解決策(どちらか)

  • 別スレッドや別プロセスにする。
  • PySimpleGUI 内部の tkinter のウィジェットにアクセスして

 matplotlib.pyplot のGUIを埋め込む方法を取る。
参考: PySimpleGUIにMatplotlibを埋め込みたい

他に、イベントループを統合させる解決方法もありますが、
PySimpleGUIでの事例(サンプルコード等)は少ないと思います。

投稿2021/01/24 07:20

teamikl

総合スコア8742

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問