ここに示す構造に基づいて、UI の応答性を維持しながら作業を行う QThread を作成する QDialog があります。完全な説明。ただし、スレッドがまだ実行されている間に reject() が呼び出された場合 (ユーザーがキャンセルを押すか、ダイアログを閉じたため)、エラーが発生します。
QThread: スレッドの実行中に破棄されました
私が望んでいるのは、ワーカーのループが早期に中断され、バックグラウンドでクリーンアップが行われることです (たとえば、いくつかのキューをクリアしたり、シグナルを送信したりします)。私は独自の「キャンセル」関数でこれを行うことができましたが、reject() (およびそれを呼び出すことができるすべての多くの方法) でうまく動作させるにはどうすればよいですか? クリーンアップを待ってダイアログをブロックしたくありません。バックグラウンドで実行し続け、正常に終了する必要があります。
問題を示す以下のサンプル コードを参照してください。どんな助けでも大歓迎です。
#!/usr/bin/env python
from PyQt4 import QtCore, QtGui
import sys
import time
class Worker(QtCore.QObject):
def __init__(self):
QtCore.QObject.__init__(self)
def process(self):
# dummy worker process
for n in range(0, 10):
print 'process {}'.format(n)
time.sleep(0.5)
self.finished.emit()
finished = QtCore.pyqtSignal()
class Dialog(QtGui.QDialog):
def __init__(self):
QtGui.QDialog.__init__(self)
self.init_ui()
def init_ui(self):
self.layout = QtGui.QVBoxLayout(self)
self.btn_run = QtGui.QPushButton('Run', self)
self.layout.addWidget(self.btn_run)
self.btn_cancel = QtGui.QPushButton('Cancel', self)
self.layout.addWidget(self.btn_cancel)
QtCore.QObject.connect(self.btn_run, QtCore.SIGNAL('clicked()'), self.run)
QtCore.QObject.connect(self.btn_cancel, QtCore.SIGNAL('clicked()'), self.reject)
self.show()
self.raise_()
def run(self):
# start the worker thread
self.thread = QtCore.QThread()
self.worker = Worker()
self.worker.moveToThread(self.thread)
QtCore.QObject.connect(self.thread, QtCore.SIGNAL('started()'), self.worker.process)
QtCore.QObject.connect(self.worker, QtCore.SIGNAL('finished()'), self.thread.quit)
QtCore.QObject.connect(self.worker, QtCore.SIGNAL('finished()'), self.worker.deleteLater)
QtCore.QObject.connect(self.thread, QtCore.SIGNAL('finished()'), self.thread.deleteLater)
self.thread.start()
def main():
app = QtGui.QApplication(sys.argv)
dlg = Dialog()
ret = dlg.exec_()
if __name__ == '__main__':
main()