gpt4 book ai didi

Python-PyQt : restarting a thread which is finished

转载 作者:行者123 更新时间:2023-12-01 08:57:17 24 4
gpt4 key购买 nike

我有 pyqt 接口(interface),如果按下按钮,它会启动 QThread。线程运行,完成后我可以再次启动它,到目前为止没有问题。我现在添加了一个用于线程连续操作的复选框。如果选中复选框,按钮将保持按下状态,并且必须再次按下按钮才能停止线程。

显然,停止后,线程已正确完成(也使用 isRunning() 方法进行检查),但如果我尝试在连续操作中再次启动它,程序将崩溃。如果我在关闭连续操作的情况下重新启动它,则不会发生这种情况,但在这种情况下线程会启动和停止两次。

如何解释这种行为?有没有办法让它按预期工作?

一个例子:

import sys
from PyQt5 import QtCore
import PyQt5.QtWidgets as QtW
from PyQt5.QtCore import QThread, pyqtSlot, pyqtSignal
import time

class MyWindow(QtW.QMainWindow):

def __init__(self):
super().__init__()
self.setWindowTitle('MyWindow')
self._main = QtW.QWidget()
self.setCentralWidget(self._main)
self.button = QtW.QPushButton('Do it', self)
self.button.clicked.connect(self.do)
self.contincheck = QtW.QCheckBox("Continuous")
self.contincheck.clicked.connect(self.continuous_doing)
self.continuous = False
self.layout = QtW.QGridLayout(self._main)
self.layout.addWidget(self.button,0,0)
self.layout.addWidget(self.contincheck,1,0)
self.setLayout(self.layout)
self.show()

def continuous_doing(self):
if self.contincheck.isChecked():
self.button.setCheckable(True)
self.continuous = True
else:
self.button.setCheckable(False)
self.continuous = False

def do(self):
if self.button.isCheckable() and not self.button.isChecked():
self.button.setText('Do it')
self.button.clicked.connect(self.do)
self.contincheck.setEnabled(True)
else:
self.mythread = MyThread(self.continuous)
if self.button.isCheckable() and self.button.isChecked():
self.button.setText('Stop doing that')
self.contincheck.setDisabled(True)
self.button.clicked.connect(self.mythread.stop)
self.mythread.finished.connect(self.thread_finished)
self.mythread.signal.connect(self.done)
self.mythread.start()

@pyqtSlot(int)
def done(self, i):
print('done it', i)

@pyqtSlot()
def thread_finished(self):
print('thread finished')



class MyThread(QThread):
signal = pyqtSignal(int)

def __init__(self, continuous):
QThread.__init__(self)
self._stopped = True
self.continuous = continuous
self.i = 0

def __del__(self):
self.wait()

def stop(self):
self._stopped = True

def run(self):
self._stopped = False
while True:
self.signal.emit(self.i)
if self._stopped:
break
if self.continuous: time.sleep(2)
else: break


if __name__ == '__main__':
app = QtCore.QCoreApplication.instance()
if app is None:
app = QtW.QApplication(sys.argv)
mainGui = MyWindow()
mainGui.show()
app.aboutToQuit.connect(app.deleteLater)
app.exec_()

最佳答案

问题是您正在创建一个新线程,而不是重用现有线程,在下面的示例中,我将向您展示如何正确执行此操作:

import sys
from PyQt5 import QtCore, QtWidgets

class MyWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle('MyWindow')
self._main = QtWidgets.QWidget()
self.setCentralWidget(self._main)
self.button = QtWidgets.QPushButton('Do it')
self.button.clicked.connect(self.do)

self.contincheck = QtWidgets.QCheckBox("Continuous")
self.contincheck.clicked.connect(self.continuous_doing)
self.continuous = False
layout = QtWidgets.QGridLayout(self._main)
layout.addWidget(self.button, 0, 0)
layout.addWidget(self.contincheck, 1, 0)

self.mythread = MyThread(self.continuous, self)
self.mythread.finished.connect(self.thread_finished)
self.button.clicked.connect(self.mythread.stop)
self.mythread.signal.connect(self.done)

def continuous_doing(self):
self.button.setCheckable(self.contincheck.isChecked())
self.continuous = self.contincheck.isChecked()

def do(self):
if self.button.isCheckable() and not self.button.isChecked():
self.button.setText('Do it')
self.contincheck.setEnabled(True)
else:
self.mythread.continuous = self.continuous
if self.button.isCheckable() and self.button.isChecked():
self.button.setText('Stop doing that')
self.contincheck.setDisabled(True)

self.mythread.start()

@QtCore.pyqtSlot(int)
def done(self, i):
print('done it', i)

@QtCore.pyqtSlot()
def thread_finished(self):
print('thread finished')


class MyThread(QtCore.QThread):
signal = QtCore.pyqtSignal(int)

def __init__(self, continuous=False, parent=None):
super(MyThread, self).__init__(parent)
self._stopped = True
self.continuous = continuous
self.i = 0

def __del__(self):
self.wait()

def stop(self):
self._stopped = True

def run(self):
self._stopped = False
while True:
self.signal.emit(self.i)
if self._stopped:
break
if self.continuous:
QtCore.QThread.sleep(2)
else:
break


if __name__ == '__main__':
app = QtCore.QCoreApplication.instance()
if app is None:
app = QtWidgets.QApplication(sys.argv)
mainGui = MyWindow()
mainGui.show()
app.aboutToQuit.connect(app.deleteLater)
app.exec_()

关于Python-PyQt : restarting a thread which is finished,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52716273/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com