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

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

新規登録して質問してみよう
ただいま回答率
85.48%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

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

Q&A

解決済

3回答

5088閲覧

tkinter 固まるのでスレッドにして別処理したい

goki_gottan

総合スコア168

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Tkinter

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

0グッド

0クリップ

投稿2020/12/10 10:37

tkinterで、for文を使用して、canvasを常時変更しているため、常時更新している状況です。
しかし、tkinterを触ったり、他の作業をすると、tkinterが応答なしとなります。処理終了後にはcanvasは更新されますが、応答なしをなくしたく、やはり別処理で実行することを考えております。

ネットで見ると、別処理threadでヒットしますが、分かりにくく、かなり構築しましたので、大きく変更はしたくないです。

そこで、分かりやすく、threadにてtkinterの応答なしをなくす構文を教えていただけないでしょうか?

def ボタンクリック()
for文
ある処理

canvas色変え

ボタン

main.loop

上記の構文ですが、簡単な構文が見当たりません。
ボタンを押すと、tkinterの処理を終了させ、for文で、ある処理と同時にcanvasを色変えしたく思います。

宜しくお願いいたします。

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

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

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

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

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

guest

回答3

0

ベストアンサー

「応答なし」になるコード例

python

1#!/usr/bin/env python3.8 2 3import tkinter as tk 4 5if __name__ == '__main__': 6 root = tk.Tk() 7 label = tk.Label(root) 8 label.pack() 9 button = tk.Button(root, text="click") 10 11 def click(): 12 for num in range(100*100): 13 label.config(text=str(num)) 14 # root.update() 15 label.config(text="DONE") 16 17 button.config(command=click) 18 button.pack() 19 root.mainloop()

この場合では、応急処置的に root.update() を呼び出す事で解消できます。
但し、処理内容に時間が掛かる場合は、定期的にイベントループの処理が呼び出されないと、
やはり応答なしになってしまいます。


スレッドの利用例

python

1#!/usr/bin/env python3.8 2 3import tkinter as tk 4from threading import Thread 5import logging 6 7if __name__ == '__main__': 8 # 関数がどのスレッド実行されているかを確認する 9 logging.basicConfig( 10 level=logging.DEBUG, 11 format="[%(threadName)-10s] %(message)s", 12 ) 13 14 root = tk.Tk() 15 label = tk.Label(root) 16 label.pack() 17 button = tk.Button(root, text="click") 18 19 def set_label(text): 20 # メインスレッドで実行 21 logging.debug("set_label: %s", text) 22 label.config(text=text) 23 24 def worker(root): 25 # ループはスレッドで実行される 26 logging.info("worker start") 27 for num in range(100*100): 28 root.after_idle(set_label, str(num)) 29 root.after_idle(set_label, str(num)) 30 31 def click(): 32 thread = Thread(target=worker, args=(root,), daemon=True) 33 thread.start() 34 35 button.config(command=click) 36 button.pack() 37 root.mainloop()

メインスレッド上でGUIは動き続けるので応答なしにはなりません。
注意点は、別スレッドからは直接 GUI の操作を行ってはいけない点に注意。

問題なく動く場合もありますが、誤動作の原因になります。

python

1 def worker(root): 2 # XXX: スレッドで実行される関数内では、直接GUIを操作しない事 3 # 通常のtkinterでは NG 4 label.config(text="...")

スレッドから直接GUIを操作するようなコードを書きたい場合は、
mtTkinter 等の、スレッドセーフな操作に内部で対応してくれるライブラリがあります。
上記のようなコードを内部でスレッド間のメッセージをやりとりして、メインスレッド上で実行します。

別スレッドからtkinterを操作する対応方法:
root.after_idle に関数を渡す事で、メインスレッドのイベントループから呼び出す事が出来ます。

python

1 def worker(root): 2 root.after_idle(lambda: label.config(text="..."))

投稿2020/12/11 12:23

teamikl

総合スコア8664

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

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

teamikl

2020/12/11 15:32

別問題のようなので削除申請しました。
guest

0

他の作業もする場合、root.updateは、tkinterが最上にきませんか?

投稿2020/12/10 11:19

goki_gottan

総合スコア168

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

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

teamikl

2020/12/11 11:55

具体的なコードを提示して質問してください。 update は待機中のイベントの内容を即時に反映するのみで、 呼び出し時に何が起こるかは直前のコード次第です。
goki_gottan

2020/12/11 13:21

すみません、threadは理解したのですが、グラフmatplotlibが表示されないんですが、これってthreadのせいってことはないですか?threadを外すと、グラフ表示できます
teamikl

2020/12/11 15:20

matplotlib を使う場合は、イベントループの競合が問題です。 plt.show() と root.mainloop() を同時に使うことはできません。 tkinter に matplotlib を組み込む方法を調べて見て下さい。
teamikl

2020/12/11 15:32 編集

出来れば、質問の際は問題が再現できるコードを提示してください。 「ある処理」の内容が matplotlib でのグラフ表示なのであれば、スレッドとは別問題です。
guest

0

簡単な方法は前回の質問で回答した通り、
定期的に update() を呼ぶ事で解消します。描画のみ更新で良い場合は update_idletasks()

python

1def ボタンクリック(): 2 for3 ある処理 4 root.update() # tkinterのイベント処理をする

ただし「ある処理」に時間が掛かる場合は、その間応答なしになります。

大きく変更はしたくないです。

残念ながら両立は出来ません。
スレッドを使う以上は、プログラム全体をスレッドセーフな設計にする必要があります。

  • 「ある処理のループ」は別スレッドで実行
  • 色変え等、GUI描画の処理はメインスレッド側で行う

投稿2020/12/10 11:03

teamikl

総合スコア8664

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

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

goki_gottan

2020/12/10 11:18

ご回答ありがとうございます。 root.update()の場合、応答なしとはならないのでしょうか?
teamikl

2020/12/10 11:44

回答通り、処理内容次第です > ただし「ある処理」に時間が掛かる場合は、その間応答なしになります。
goki_gottan

2020/12/11 18:42

ありがとうございます。 追加の質問は、他の質問にします。 無事、threadingでき、更新もできました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問