如何在 tkinter 关闭窗口时停止工作线程?

huangapple go评论97阅读模式
英文:

How can I stop a worker thread in tkinter when window is closed?

问题

当我关闭tkinter窗口时,工作线程正在运行时,10秒后我会得到这个错误:RuntimeError: main thread is not in main loop,可能是因为ROOT被销毁。

import tkinter as tk
from tkinter import ttk
import threading
import time


def worker(event_ready):
    event_ready.wait()

    progress_bar = ttk.Progressbar(ROOT, orient='horizontal', mode='indeterminate', length=280)
    progress_bar.grid(column=0, row=0, columnspan=2, padx=10, pady=20)

    progress_bar.start()
    time.sleep(10)
    progress_bar.stop()


event_ready = threading.Event()
worker_thread = threading.Thread(target=worker, args=(event_ready,))
worker_thread.start()

global ROOT
ROOT = tk.Tk()
ROOT.geometry('300x120')
ROOT.title('TEST')
ROOT.grid()
event_ready.set()
ROOT.mainloop()

如何在我关闭窗口时尽快停止工作线程?

英文:

When I close the tkinter window while the worker thread is running I get this error after 10 seconds: RuntimeError: main thread is not in main loop probably because ROOT is destroyed.

import tkinter as tk
from tkinter import ttk
import threading
import time


def worker(event_ready):
    event_ready.wait()

    progress_bar = ttk.Progressbar(ROOT, orient='horizontal', mode='indeterminate', length=280)
    progress_bar.grid(column=0, row=0, columnspan=2, padx=10, pady=20)

    progress_bar.start()
    time.sleep(10)
    progress_bar.stop()



event_ready = threading.Event()
worker_thread = threading.Thread(target=worker, args=(event_ready,))
worker_thread.start()

global ROOT
ROOT = tk.Tk()
ROOT.geometry('300x120')
ROOT.title('TEST')
ROOT.grid()
event_ready.set()
ROOT.mainloop()

How can stop worker thread a soon as I close window?

答案1

得分: 1

你只需将线程设置为守护线程,至少在Windows中是这样。

worker_thread = threading.Thread(target=worker, args=(event_ready,), daemon=True)

现在当你关闭窗口时,程序会立即终止。

英文:

You simply only need to start the Thread as a daemon, at least in Windows.

worker_thread = threading.Thread(target=worker, args=(event_ready,), daemon=True)

Now when you close the Window, the program will terminate immediately.

答案2

得分: 0

要在关闭tkinter窗口时立即停止工作线程,您可以使用Tk类中的protocol方法来处理窗口关闭事件。这允许您定义一个在窗口关闭时调用的函数。

import tkinter as tk
from tkinter import ttk
import threading
import time

def worker(event_ready, stop_event):
    event_ready.wait()
    progress_bar = ttk.Progressbar(
        ROOT,
        orient='horizontal',
        mode='indeterminate',
        length=280
    )
    progress_bar.grid(column=0, row=0, columnspan=2, padx=10, pady=20)

    progress_bar.start()
    while not stop_event.is_set():
        time.sleep(0.1)
    progress_bar.stop()
    ROOT.destroy()

def on_closing():
    stop_event.set()

event_ready = threading.Event()
stop_event = threading.Event()
worker_thread = threading.Thread(target=worker, args=(event_ready, stop_event), daemon=True)
worker_thread.start()

ROOT = tk.Tk()
ROOT.geometry('300x120')
ROOT.title('TEST')
ROOT.grid()
event_ready.set()

ROOT.protocol("WM_DELETE_WINDOW", on_closing) 
ROOT.mainloop()

on_closing 函数通过ROOT.protocol绑定到窗口的关闭事件,并简单地设置stop_event标志,从而通知工作线程停止。

这样,当您关闭tkinter窗口时,on_closing 函数将被调用,停止工作线程,然后窗口将会被优雅地关闭。

英文:

To stop the worker thread as soon as you close the tkinter window, you can use the protocol method in the Tk class to handle the window closing event. This allows you to define a function that will be called when the window is closed.

import tkinter as tk
from tkinter import ttk
import threading
import time

def worker(event_ready, stop_event):
    event_ready.wait()
    progress_bar = ttk.Progressbar(
        ROOT,
        orient='horizontal',
        mode='indeterminate',
        length=280
    )
    progress_bar.grid(column=0, row=0, columnspan=2, padx=10, pady=20)

    progress_bar.start()
    while not stop_event.is_set():
        time.sleep(0.1)
    progress_bar.stop()
    ROOT.destroy()


def on_closing():
    stop_event.set()


event_ready = threading.Event()
stop_event = threading.Event()
worker_thread = threading.Thread(target=worker, args=(event_ready, stop_event), daemon=True)
worker_thread.start()

ROOT = tk.Tk()
ROOT.geometry('300x120')
ROOT.title('TEST')
ROOT.grid()
event_ready.set()

ROOT.protocol("WM_DELETE_WINDOW", on_closing) 
ROOT.mainloop()

The on_closing function is bound to the window's closing event using ROOT.protocol, and it simply sets the stop_event flag, signaling the worker thread to stop.

This way, when you close the tkinter window, the on_closing function will be called, stopping the worker thread, and then the window will be closed gracefully.

huangapple
  • 本文由 发表于 2023年7月24日 14:57:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76752059.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定