Python 如何从GUI停止QThread
这是我先前发布的一个问题的后续问题。 问题在于,当使用建议的方法(不是子类化QThread,而是创建QObject,然后将其移动到QThread)时,如何从GUI停止(终止|退出|退出)QThread。下面是一个工作示例。我可以启动GUI和Qthread,然后让后者更新GUI。然而,我无法阻止它。我为qthread尝试了几种方法(quit()、exit(),甚至terminate()),但都没有成功。 非常感谢你的帮助 以下是完整的代码:Python 如何从GUI停止QThread,python,pyqt,pyqt4,qthread,Python,Pyqt,Pyqt4,Qthread,这是我先前发布的一个问题的后续问题。 问题在于,当使用建议的方法(不是子类化QThread,而是创建QObject,然后将其移动到QThread)时,如何从GUI停止(终止|退出|退出)QThread。下面是一个工作示例。我可以启动GUI和Qthread,然后让后者更新GUI。然而,我无法阻止它。我为qthread尝试了几种方法(quit()、exit(),甚至terminate()),但都没有成功。 非常感谢你的帮助 以下是完整的代码: import time, sys from PyQt4.
import time, sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
class SimulRunner(QObject):
'Object managing the simulation'
stepIncreased = pyqtSignal(int, name = 'stepIncreased')
def __init__(self):
super(SimulRunner, self).__init__()
self._step = 0
self._isRunning = True
self._maxSteps = 20
def longRunning(self):
while self._step < self._maxSteps and self._isRunning == True:
self._step += 1
self.stepIncreased.emit(self._step)
time.sleep(0.1)
def stop(self):
self._isRunning = False
class SimulationUi(QDialog):
'PyQt interface'
def __init__(self):
super(SimulationUi, self).__init__()
self.goButton = QPushButton('Go')
self.stopButton = QPushButton('Stop')
self.currentStep = QSpinBox()
self.layout = QHBoxLayout()
self.layout.addWidget(self.goButton)
self.layout.addWidget(self.stopButton)
self.layout.addWidget(self.currentStep)
self.setLayout(self.layout)
self.simulRunner = SimulRunner()
self.simulThread = QThread()
self.simulRunner.moveToThread(self.simulThread)
self.simulRunner.stepIncreased.connect(self.currentStep.setValue)
self.stopButton.clicked.connect(simulThread.qui) # also tried exit() and terminate()
# also tried the following (didn't work)
# self.stopButton.clicked.connect(self.simulRunner.stop)
self.goButton.clicked.connect(self.simulThread.start)
self.simulThread.started.connect(self.simulRunner.longRunning)
self.simulRunner.stepIncreased.connect(self.current.step.setValue)
if __name__ == '__main__':
app = QApplication(sys.argv)
simul = SimulationUi()
simul.show()
sys.exit(app.exec_())
导入时间,系统
从PyQt4.QtCore导入*
从PyQt4.QtGui导入*
类SimulRunner(QObject):
“管理模拟的对象”
stepIncreased=pyqtSignal(int,name='stepIncreased')
定义初始化(自):
超级(SimulRunner,self)。\uuuu init\uuuuu()
自。_步=0
self.\u isRunning=True
自。_最大步数=20
def长时间运行(自):
当self.\u steplonglunning()
方法)
问题是,次线程只有在运行自己的事件循环时才能响应信号。常规的Qthread(我的代码使用的是)没有。不过,将QThread子类化以实现这一效果非常容易:
class MyThread(QThread):
def run(self):
self.exec_()
并在我的代码中使用了self.simulThread=MyThread()
,而不是原来的self.simulThread=Qthread()
。
这可确保次线程运行事件循环。但这还不够。longRunning()
方法需要有机会实际处理从主线程发出的事件。在的帮助下,我发现在longlunning()
方法中简单地添加QApplication.processEvent()
给了次线程这样的机会。我现在可以停止在辅助线程中执行的处理,即使我还没有弄清楚如何停止线程本身
结束。我的longRunning方法现在如下所示:
def longRunning(self):
while self._step < self._maxSteps and self._isRunning == True:
self._step += 1
self.stepIncreased.emit(self._step)
time.sleep(0.1)
QApplication.processEvents()
欢迎评论 我知道这是很久以前的事了,但我只是被同样的问题绊倒了 我也一直在寻找一个合适的方法来做到这一点。最后很容易。退出应用程序时,任务需要停止,线程需要停止调用其quit方法。请参阅底部的停止线程方法。您需要等待线程完成。否则,您将在线程仍在运行时在退出时收到“QThread:destromed”消息 (我还将代码更改为使用pyside) 导入时间,系统 从PySide.QtCore导入* 从PySide.QtGui导入* 班级工作人员(QObject): “管理模拟的对象” 步长增加=信号(int) 定义初始化(自): 超级(工作者,自我)。\uuuu初始化 自。_步=0 self.\u isRunning=True 自。_最大步数=20 def任务(自我): 如果不是自运行,请执行以下操作: self.\u isRunning=True 自。_步=0 当self.\u step
self.simulThread = MyThread()
self.simulRunner.moveToThread(self.simulThread)
self.stopButton.clicked.connect(self.simulRunner.stop)
import time, sys
from PySide.QtCore import *
from PySide.QtGui import *
class Worker(QObject):
'Object managing the simulation'
stepIncreased = Signal(int)
def __init__(self):
super(Worker, self).__init__()
self._step = 0
self._isRunning = True
self._maxSteps = 20
def task(self):
if not self._isRunning:
self._isRunning = True
self._step = 0
while self._step < self._maxSteps and self._isRunning == True:
self._step += 1
self.stepIncreased.emit(self._step)
time.sleep(0.1)
print "finished..."
def stop(self):
self._isRunning = False
class SimulationUi(QDialog):
def __init__(self):
super(SimulationUi, self).__init__()
self.btnStart = QPushButton('Start')
self.btnStop = QPushButton('Stop')
self.currentStep = QSpinBox()
self.layout = QHBoxLayout()
self.layout.addWidget(self.btnStart)
self.layout.addWidget(self.btnStop)
self.layout.addWidget(self.currentStep)
self.setLayout(self.layout)
self.thread = QThread()
self.thread.start()
self.worker = Worker()
self.worker.moveToThread(self.thread)
self.worker.stepIncreased.connect(self.currentStep.setValue)
self.btnStop.clicked.connect(lambda: self.worker.stop())
self.btnStart.clicked.connect(self.worker.task)
self.finished.connect(self.stop_thread)
def stop_thread(self):
self.worker.stop()
self.thread.quit()
self.thread.wait()
if __name__ == '__main__':
app = QApplication(sys.argv)
simul = SimulationUi()
simul.show()
sys.exit(app.exec_())