Окно в Tkinter зависает при использовании thread.join()
У меня есть окно с кнопками старт и стоп. При нажатии "стоп" программка зависает. Мне хотелось,чтобы func() заработала после завершения потока.
def btn_start():
thread.start()
def btn_stop():
event.set()
thread.join()
func()
Ответы (2 шт):
Автор решения: Storm PC
→ Ссылка
Попробуй вот так:
import threading
event = threading.Event()
def func():
print("Hello, world!") # просто пример
def btn_start():
global thread
thread =
threading.Thread(target=func)
thread.start()
def btn_stop():
event.set()
thread.join()
func() # лишняя строка, функция будет вызвана автоматически после завершения потока
Автор решения: insolor
→ Ссылка
Просто не используйте .join(). Использование этого метода блокирует основной поток (на то время, пока поток не завершится), и не дает выполняться циклу обработки событий tkinter.
Функцию можно вызвать прямо из выполняемого потока, когда внутренний цикл завершится, пример:
import threading
import time
import tkinter as tk
import tkinter.ttk as ttk
event = threading.Event()
def loop():
i = 0
while not event.is_set():
label.config(text=i)
time.sleep(1.0)
i += 1
func()
def func():
label.config(text="Stopped")
def btn_start():
global thread
thread = threading.Thread(target=loop, daemon=True)
thread.start()
def btn_stop():
event.set()
root = tk.Tk()
label = tk.Label(root)
label.pack()
tk.Button(root, text="Start", command=btn_start).pack()
tk.Button(root, text="Stop", command=btn_stop).pack()
root.mainloop()
Если нужно выполнять именно из основного потока, то делаете периодическую проверку, жив ли поток (через метод .is_alive(), как предложил @Сергей Кох), и если нет - то выполнить функцию, если еще жив, то проверить чуть позже:
def btn_stop():
event.set()
check_thread_finished()
def check_thread_finished():
if thread.is_alive():
root.after(100, check_thread_finished) # выполнить эту же функцию через 100 мс
return
func()