如何将窗口关闭(红色X)链接到PyQt中关闭所有线程的函数?

1 投票
1 回答
2642 浏览
提问于 2025-04-18 11:35

我现在正在开发一个图形用户界面(GUI)应用程序,使用的是 PyQt

这个GUI的功能涉及到多个线程。我猜这就是为什么当我点击窗口右上角的红色“x”时,

程序并没有完全关闭(尽管界面看起来消失了)。

有没有办法把主窗口的“x”按钮和一个关闭功能连接起来,这样可以停止所有的线程?

我对 PyQt 还不太熟悉,所以请多多包涵!(另外,我相信我所有的线程都是Python线程,而不是Q线程)

1 个回答

1

你可以在启动线程之前,把Thread对象的daemon标志设置为True。根据文档的说明:

一个线程可以被标记为“守护线程”。这个标记的意思是,当程序中只剩下守护线程时,整个Python程序会退出。这个标记的初始值是从创建它的线程继承来的。你可以通过daemon属性来设置这个标记。

值得注意的是,这样做可能会有风险,具体取决于你的后台线程在做什么(再次引用文档):

守护线程在程序关闭时会被突然停止。它们的资源(比如打开的文件、数据库事务等)可能不会被正确释放。如果你希望你的线程能够优雅地停止,就要把它们设置为非守护线程,并使用合适的信号机制,比如Event

实现优雅关闭的方式有点依赖于你线程代码的具体实现,但大致会像这样:

线程方法:

def threaded_method(event, ...):
    while True:
       if event.is_set()
           # clean up
           return
       # Normal stuff it does goes here.

主线程:

def on_exit(): # called when X in main window pressed
    event.set() # Tell threads to cleanup.
    # Do normal exit stuff.

if __name__ == "__main__":
    event = threading.Event()
    t = threading.Thread(target=threaded_method, args=(event, ...))
    #t.daemon = True # Assuming you don't care about gracefully stopping the threads, you can just do this and leave out the Event stuff.
    t.start()
    # other stuff

需要注意的是,如果你的线程中的循环在某些事情上被阻塞(比如从子进程获取数据),而这些事情在程序退出时不会解除阻塞,那么这种方法可能就不奏效。如果是这种情况,请告诉我,我可以重新调整我的回答来解决这个问题。

撰写回答