在pyqt 5/pythonx 3中,当主GUI窗口关闭时,子线程不会关闭

ncecgwcz  于 2023-10-21  发布在  Python
关注(0)|答案(1)|浏览(141)

我尝试了StackOverflow的这个例子:
在pyqt 5/ python 3中,如何在主GUI窗口关闭时关闭子线程?
我希望这个子线程在我关闭主应用程序时终止。在这个例子中,子线程是一个简单的计数器。当我关闭主GUI时,计数器仍然继续运行。如何在GUI窗口关闭时结束线程?
我的代码在这里:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Apr 11 12:41:26 2020

@author: Pietro
"""

from PyQt5 import QtWidgets
from PyQt5.QtWidgets import (QWidget, QApplication,QPushButton, 
                             QVBoxLayout)
from PyQt5.QtCore import QThread
import time, threading, sys



class testScriptApp(QtWidgets.QWidget):

    def __init__(self, parent=None):
        # initialize the widget
        QtWidgets.QWidget.__init__(self, parent)
        # set the window title
        self.setWindowTitle("Scripting")
        # manage the layout
        self.center()
        self.resize(400,400)
        self.mainGrid = QVBoxLayout()
        self.button = QPushButton('Start')
        self.button.clicked.connect(self.on_click)
        self.mainGrid.addWidget(self.button)
        self.setLayout(self.mainGrid)


    def center(self):
        qr = self.frameGeometry()
        cp = QtWidgets.QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def on_click(self):
        global running
        print('global running : ' , running)
        self.worker = Worker()
        self.worker.run()

    def closeEvent(self, event):
        global running
        running = False
        print('Closing')
#       self.worker.terminate()
        event.accept()

class Worker(QThread):

    def __init__(self):
        QThread.__init__(self)

    def run(self):
        count=1
        global running
        while count>0 and not running:
#        while count>0:
            print('counter on: ',count, running)
            time.sleep(2)
            count+=1
        else:
            print('out of loop')
            return

if __name__ == "__main__":
    running = False
    app = QtWidgets.QApplication(sys.argv)
    myapp = testScriptApp()
    myapp.show()
    app.exec_()

我在3周前开始尝试学习Python,所以请温柔一点。我做错了什么?

von4xj4u

von4xj4u1#

来自:QThread:run()Vs start()
从医生那里
QThread在run()中开始执行。要创建自己的线程,子类化QThread并重新实现run()使用start()方法开始执行。当你从run()返回时,执行结束,就像应用程序离开main()时一样。要创建自己的线程,你总是需要子类化QThread并重新实现run()。要启动线程,您需要调用start()。
我希望现在已经清楚了。
就像alec说的
你应该叫
.worker.start()而不是run()
如果设置self.worker.setTerminationEnabled(True)
然后在closeEvent
self.worker.terminate()将终止线程。-
更改代码:

from PyQt5 import QtWidgets
from PyQt5.QtWidgets import (QWidget, QApplication,QPushButton, 
                             QVBoxLayout)
from PyQt5.QtCore import QThread
import time, threading, sys



class testScriptApp(QtWidgets.QWidget):

    def __init__(self, parent=None):
        # initialize the widget
        QtWidgets.QWidget.__init__(self, parent)
        # set the window title
        self.setWindowTitle("Scripting")
        # manage the layout
        self.center()
        self.resize(400,400)
        self.mainGrid = QVBoxLayout()
        self.button = QPushButton('Start')
        self.button.clicked.connect(self.on_click)
        self.mainGrid.addWidget(self.button)
        self.setLayout(self.mainGrid)


    def center(self):
        qr = self.frameGeometry()
        cp = QtWidgets.QDesktopWidget().availableGeometry().center()
        qr.moveCenter(cp)
        self.move(qr.topLeft())

    def on_click(self):
        global running
        print('global running : ' , running)
        self.worker = Worker()
        
        self.worker.setTerminationEnabled(True)
        self.worker.start()

    def closeEvent(self, event):
        global running
        
        # running = False ## doesnt print 'out of loop' line
        running = True ## does print 'out of loop' line
        
        # self.worker.terminate() # if not commented out doesnt print the 'out of loop' line
        
        ### self.worker Execution ends when you return from run() 
        
        time.sleep(5)
        
        print('Closing')

        event.accept()

class Worker(QThread):

    def __init__(self):
        QThread.__init__(self)

    def run(self):
        count=1
        global running
        while count>0 and not running:
            print('counter on: ',count, running)
            time.sleep(2)
            count+=1
        else:
            print('out of loop')
            return

if __name__ == "__main__":
    running = False
    app = QtWidgets.QApplication(sys.argv)
    myapp = testScriptApp()
    myapp.show()
    app.exec_()

产出:

global running :  False
counter on:  1 False
counter on:  2 False
out of loop
Closing

取消注解self.worker.terminate(),输出:

global running :  False
counter on:  1 False
counter on:  2 False
counter on:  3 False
counter on:  4 False
counter on:  5 False
Closing

请注意,我在closeEvent中添加了time.sleep(5),以允许Qthread打印out of loop行。
请记住,在上面的链接中self.worker执行结束时,你从run()返回允许终止与self.worker.setTerminationEnabled(True)将允许在任何时候调用self.worker.terminate()

相关问题