0
2

More than 1 year has passed since last update.

【tkinter + threading】tkinterで無限ループのスレッドを正常に終了させる方法

Posted at

1. きっかけ

シリアル通信をするGUIアプリを作っていました。
すると、応答を待っている間のコンマ数秒アプリがフリーズすることに気付きました。
微妙な差ですがストレスに感じたので解決策を講じました。

2. 結論

  • QUITボタンを作り、そのボタンで呼ばれる関数内でスレッドを終了させる
  • 無限ループはフラグが立ったら抜け出すようにしておく
  • アプリをバツボタンで閉じられるとスレッドが無限ループから抜出せず強制終了するしかなくなるので、バツボタンで閉じられないように設定

3. 実装

  • サンプルアプリ
class App(tk.Frame):
    def __init__(self, master):
        super().__init__(master)

        # ウィジェット作成
        self.number = tk.IntVar(value=0)
        self.label_number = tk.Label(master, textvariable=self.number)
        self.button_quit = tk.Button(master, text='QUIT', command=self.quit)
        self.label_number.pack()
        self.button_quit.pack()
        
        # スレッド
        self.quit_flag = False
        self.thread = threading.Thread(target=self.infinite_func)
        self.thread.start()
  • 無限ループの関数
    def infinite_func(self):
        while not self.quit_flag:
            # 数を1ずつ増やす
            self.number.set(self.number.get() + 1)
            time.sleep(1)
  • 終了処理
    def quit(self):
        # フラグを立てる
        self.quit_flag = True
        # スレッドの終了を待つ(ウィンドウを閉じる前に!)
        self.thread.join()
        # ウィンドウを閉じる
        self.master.destroy()
  • main
def main():
    root = tk.Tk()
    root.protocol('WM_DELETE_WINDOW', (lambda: 'pass')())  # QUITボタン以外の終了操作を許可しない
    app = App(master=root)
    app.mainloop()


if __name__ == '__main__':
    main()

4. 終わりに

コードはGitHubに挙げておきます。
https://github.com/PlusF/TkinterThreadingSample

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2