質問: ### 前提・実現したいこと 今、threadingで呼び出された関数が無限にループする処理のあるアプリをtkinterで作りました。 ### 発生している問題・エラーメッセージ 無限ループ中、×ボタン押して画面を閉じることは出来るのですが、画面をドラッグ等で動かそうとすると、関数の処理は続行したままで、キーボードで画面切り替え等を行わない限りマウスで何も操作できなくなりました。 ### 該当のソースコード ``` import tkinter as tk import threading import time class App(object): def __init__(self): self.text001=time.time() root=tk.Tk() self.label=tk.Label(root,text=self.text001) self.label.pack() threading.Thread(target=self.Update).start() root.mainloop() def Update(self): while True: self.text001=time.time() self.label["text"]=self.text001 app=App() ``` ### 試したこと こうなる原因は、おそらく普通は起動された画面をドラッグすると内部処理がその間は止まる?という仕様になっていると思うのですが、、、どうすれば、ドラッグ時は内部処理に影響を与えないようにすることができるのでしょうか? ### 補足情報(FW/ツールのバージョンなど) ここにより詳細な情報を記載してください。
回答: > > こうなる原因は、おそらく普通は起動された画面をドラッグすると内部処理がその間は止まる?という仕様になっていると思うのですが、、、 > > > 自分の知識では正確な動作を言えませんが、原因はおそらく `self.label["text"] = self.text001` この行があまりに頻繁に実行されるためTcl/Tkウィンドウへのイベントキューにイベントが大量にキューされている、ないしはTcl/Tkがラベルウィジェットの内容を画面へ更新する処理が頻繁に行われるため、OSからのタイトルバーへのマウスイベントをTcl/Tkのランタイムによる「タイトルのドラッグ=>ウィンドウの位置の変更」のイベントハンドラーの起動が普通の動作頻度で動けないためだと思います。 > > どうすれば、ドラッグ時は内部処理に影響を与えないようにすることができるのでしょうか? > > > 逆に考えるべきと思います。Tcl/Tkが最低限の頻度でイベントに反応できるよう、Tcl/Tkへのウィンドウへの要求頻度を下げればよいでしょう。 具体的にはupdateを次のようにすればよいと思います。 ``` def Update(self): while True: time.sleep(0.01) # 10ms程度イベントループが動作できる余地を与える self.text001=time.time() self.label["text"]=self.text001 ``` 10msにした理由は、自分のPC(Windows10 64bit)ではそれより小さい値を指定しても実際にスレッドが停止する時間が10ms程度よりは小さくならない(OSのタイマー割り込みによるスケジューリングの精度がその程度の精度になっている?)からです。