質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.46%
Matplotlib

MatplotlibはPythonのおよび、NumPy用のグラフ描画ライブラリです。多くの場合、IPythonと連携して使われます。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

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

Q&A

解決済

2回答

4638閲覧

tkinterウィンドウを閉じないとpltshowが実行されない

nodahourou

総合スコア2

Matplotlib

MatplotlibはPythonのおよび、NumPy用のグラフ描画ライブラリです。多くの場合、IPythonと連携して使われます。

Tkinter

Tkinterは、GUIツールキットである“Tk”をPythonから利用できるようにした標準ライブラリである。

Python

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

0グッド

0クリップ

投稿2020/11/13 09:29

編集2020/11/14 03:16

tkinterのウィンドウとplt.showの共存

現在,tkinterでメインウィンドウを表示し,ウィンドウ内のボタンをクリックすることで関数を呼び出し,随時処理を行うようにしています.

呼び出した関数内でplt.showを呼び出すと,処理が停止しますが,
tkinterで表示したメインウィンドウも閉じないと続きの処理が実行されず困っています.

以前MACの環境で実行した際は,tkinterの画面を閉じることなく,plt.showの画面を閉じることで続きの処理が実行されていたので,非常に困っています

改善方法などありますでしょうか.
よろしくお願いします.

from PIL import Image, ImageTk import numpy as np import tkinter as tk import tkinter.ttk as ttk import tkinter.filedialog as tkfd import cv2 if __name__ == "__main__": root = tk.Tk() root.title("") root.geometry("") btn1 = tk.Button(root) btn1.configure(text="test", command=func.img_open) btn1.pack(anchor="ne") root.mainloop() def img_open(): img1 = cv2.imread('1.png') img2 = cv2.imread('2.png') img3 = cv2.imread('3.png') plt.imshow(img1) plt.show() plt.imshow(img2) #以降の処理がメインウィンドウを閉じてから実行される plt.show() plt.imshow(img3) plt.show()

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

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

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

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

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

teamikl

2020/11/13 16:27

> tkinterで表示したメインウィンドウも閉じないと続きの処理が実行されず困っています. 実際に問題を再現できる最小限のコードを提示してください。
guest

回答2

0

ベストアンサー

tkinterのウィンドウとplt.showの共存については、
「イベントループ」の理解が必須です。

GUIのライブラリは、描画やマウス・キー入力のイベント処理の為に
イベントループを持っているのですが、
tkinter と同時に使う場合、それぞれのライブラリがイベントループを持っているので、
まずは、どちらのイベントループを主体にするか決める必要があります。

tkinter の mainloop を使う場合は、plt.show は共存できません。
そのままでは、片方のイベントループ中、
もう片方のイベントループは止まった状態になっています。
(共存させる方法については後述)

呼び出した関数内でplt.showを呼び出すと,処理が停止しますが

は、片方のイベントループしか機能してない状態です。

以前MACの環境で実行した際は,tkinterの画面を閉じることなく,plt.showの画面を閉じることで続きの処理が実行されていたので,非常に困っています

plt.show の処理は、バックエンドとなるGUIに依存するので、
環境の違いが影響します。


目的が「プロット画面を表示したい」or 「共存の手段自体を知りたい」かで
変わってきますが、

前者であれば tkinter のイベントループ(mainloop)を使う場合は
plt.show は使わずに、同じような挙動が必要であれば、
モーダルダイアログを作成しその中にプロットを表示します。

後者の場合、共存の方法・両方のイベントループを両立させる方法は、
イベントループ内でもう片方のイベントループの処理が進むように、
定期的に他方の処理を呼び出す事です。

イベントループについては、
他の回答で説明したことがあるので、下記を参照してください。


参考:
tkinter上にmatplotlibのグラフを表示し、canvas内でマウス操作をできるようにしたい

投稿2020/11/13 16:44

編集2020/11/14 01:04
teamikl

総合スコア8664

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

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

nodahourou

2020/11/14 01:53

回答ありがとうございます. 目的は「プロット画面を表示したい」です. モーダルダイアログを用いた表示方法について検討したいのですが,上記のコードのように1つの関数内で複数の表示(画像やグラフ等)を行うことは可能でしょうか.
teamikl

2020/11/14 02:30

複数のダイアログを同時に開くなら、 モーダルではなく通常のダイアログですね。 一つづつ順番に表示ならモーダル・ダイアログです。 以下の方法を順番に検討して見て下さい - tkinter でのダイアログの作成方法 (tkinter.Toplevelを使う) - プロットをtkinterのウィジェット内に配置 (matplotlib の FigureCanvasTkAggを使う) ---- このコードでは root.mainloop を呼んでいないので、 通常の実行では、ウィンドウを開くことなく終了してしまうはずです。 jupyter 等の対話環境での実行でしょうか? イベントハンドラの記述方法など、 どちらのイベントループを使うかで変わってくる部分もあります。
teamikl

2020/11/14 02:38

> 1つの関数内で複数の表示(画像やグラフ等)を行うことは可能でしょうか. 注意が必要な点ですが、 イベント・ハンドラ(この場合は func.img_open関数) は、 イベントループから呼び出される為、 時間の掛かるループや、ブロッキング操作(この場合は plt.show) があると元のイベントループに処理が戻らず、 GUI 等であれば応答なしとなってしまいます。 イベント・ハンドラに登録する関数は極力、 直ぐに実行が終了するようにします。 モーダルウィンドウ等の、 ウィンドウが閉じられるのを待つ操作であれば、 関数内で待機も有りえますが、その場合でも 元のイベントループを回す対策を取ります。
nodahourou

2020/11/14 03:26

参考になります.ありがとうございます! root.mainloopが抜けていました.修正致しました. 提案して頂いた方法を試してみたいと思います.
teamikl

2020/11/14 03:48

>tkinterで表示したメインウィンドウも閉じないと続きの処理が実行されず困っています. この現象の原因についてですが: plt.show もイベントループなので、 ウィンドウを全て閉じないと、イベントループを抜けない為。 例えば、ウィンドウを開いているときに、 もう一度ボタンを押してウィンドウを閉じると 合計6枚の画像が表示されるはずです。 root.mainloop()  img_open()   plt.show()    img_open() 2回目は mainloopに戻らず、plt.show 内で実行される     plt.show() ... と関数呼び出しが深くなる     ...
guest

0

tkinter でも png 画像は読み込めるので、
このプログラムの場合は cv2 を使う必要はありませんが、
元のコードを動かす方法。

画像の部分は、実際のケースではプロットを表示するなら
tk.Canvas の代わりに FigureCanvasTkAgg を使います。

参考: matplotlib -- Embedding in Tk

python

1 2import tkinter as tk 3import tkinter.ttk as ttk 4 5from matplotlib import pyplot as plt 6from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg 7import cv2 8from PIL import Image, ImageTk 9 10class TkPlotWindow: 11 """ 12 tk組込用の pyplot の代替クラス 13 """ 14 15 def __init__(self, master): 16 self.master = master 17 self.image = None 18 19 def imshow(self, image): 20 # 画像を tk で扱える形に変換 21 image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) 22 image = Image.fromarray(image) 23 self.image = ImageTk.PhotoImage(image) 24 25 def show(self, modal=True): 26 image = self.image 27 if not image: 28 return 29 30 width, height = image.width(), image.height() 31 cx, cy = width//2, height//2 32 33 # ダイアログ生成 34 top = tk.Toplevel(self.master) 35 top.image = self.image 36 canvas = tk.Canvas(top, width=width, height=height) 37 canvas.create_image(cx, cy, image=self.image) 38 canvas.pack(fill=tk.BOTH, expand=tk.YES) 39 40 if modal: 41 # ウィンドウが閉じられるまで待つ 42 top.grab_set() 43 top.wait_window(top) # <-- イベントループ 44 45 46def img_open(): 47 img1 = cv2.imread('1.png') 48 img2 = cv2.imread('2.png') 49 img3 = cv2.imread('3.png') 50 51 plt = TkPlotWindow(root) # NOTE: <-- 代替クラスを使う 52 plt.imshow(img1) 53 plt.show() 54 plt.imshow(img2) 55 plt.show() 56 plt.imshow(img3) 57 plt.show() 58 59 60if __name__ == "__main__": 61 root = tk.Tk() 62 root.title("") 63 root.geometry("") 64 btn1 = tk.Button(root) 65 btn1.configure(text="test", command=img_open) 66 btn1.pack(anchor="ne") 67 68 # ※ matplotlib 組み込みの場合必要な終了処理 69 def _quit(): 70 root.quit() 71 root.destroy() 72 root.protocol("WM_DELETE_WINDOW", _quit) 73 74 root.mainloop() 75

投稿2020/11/14 05:32

teamikl

総合スコア8664

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

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

nodahourou

2020/11/14 14:59

回答ありがとうございます. 具体例も示して頂き,さっそく実装しました 実現したかった内容を満たすことができました. 非常に参考になりました.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問