QThread在发送终止后未停止
这段代码的问题在于,当你按下取消按钮时,工作线程并没有停止。而且,函数pdialog(self)也不会停止,直到它的循环结束。我想要的是在进度条停止显示进度的时候,同时也能停止后台的处理过程。
import sys
from PyQt4 import QtGui, QtCore
import time
#from t6 import Ui_dialog_progress
#from t6 import Ui_dialog_file
try:
_fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
_fromUtf8 = lambda s: s
class Ui_dialog_progress(object):
def setupUi(self, dialog_progress):
dialog_progress.setObjectName("dialog_progress")
dialog_progress.resize(401, 165)
self.gridLayout = QtGui.QGridLayout(dialog_progress)
self.gridLayout.setObjectName("gridLayout")
self.lblFileName = QtGui.QLabel(dialog_progress)
self.lblFileName.setText("")
self.lblFileName.setObjectName("lblFileName")
self.gridLayout.addWidget(self.lblFileName, 0, 0, 1, 2)
self.pbarFileSize = QtGui.QProgressBar(dialog_progress)
self.pbarFileSize.setProperty("value", 0)
self.pbarFileSize.setObjectName("pbarFileSize")
self.gridLayout.addWidget(self.pbarFileSize, 1, 0, 1, 2)
self.label_2 = QtGui.QLabel(dialog_progress)
self.label_2.setObjectName("label_2")
self.gridLayout.addWidget(self.label_2, 2, 0, 1, 1)
self.pbarTotal = QtGui.QProgressBar(dialog_progress)
self.pbarTotal.setProperty("value", 0)
self.pbarTotal.setObjectName("pbarTotal")
self.gridLayout.addWidget(self.pbarTotal, 3, 0, 1, 2)
self.lblTotal = QtGui.QLabel(dialog_progress)
self.lblTotal.setText("")
self.lblTotal.setObjectName("lblTotal")
self.gridLayout.addWidget(self.lblTotal, 4, 0, 1, 2)
spacerItem = QtGui.QSpacerItem(213, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
self.gridLayout.addItem(spacerItem, 6, 0, 1, 1)
spacerItem1 = QtGui.QSpacerItem(20, 5, QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Expanding)
self.gridLayout.addItem(spacerItem1, 5, 1, 1, 1)
self.btnPbarCancel = QtGui.QPushButton(dialog_progress)
self.btnPbarCancel.setObjectName("btnPbarCancel")
self.gridLayout.addWidget(self.btnPbarCancel, 6, 1, 1, 1)
self.retranslateUi(dialog_progress)
QtCore.QMetaObject.connectSlotsByName(dialog_progress)
def retranslateUi(self, dialog_progress):
dialog_progress.setWindowTitle(QtGui.QApplication.translate("dialog_progress", "Dialog", None, QtGui.QApplication.UnicodeUTF8))
self.label_2.setText(QtGui.QApplication.translate("dialog_progress", "Total:", None, QtGui.QApplication.UnicodeUTF8))
self.btnPbarCancel.setText(QtGui.QApplication.translate("dialog_progress", "Cancel", None, QtGui.QApplication.UnicodeUTF8))
class Ui_dialog_file(object):
def setupUi(self, dialog_file):
dialog_file.setObjectName(_fromUtf8("dialog_file"))
dialog_file.resize(101, 59)
self.btnCreate = QtGui.QPushButton(dialog_file)
self.btnCreate.setGeometry(QtCore.QRect(10, 20, 77, 25))
self.btnCreate.setObjectName(_fromUtf8("btnCreate"))
self.retranslateUi(dialog_file)
QtCore.QMetaObject.connectSlotsByName(dialog_file)
def retranslateUi(self, dialog_file):
dialog_file.setWindowTitle(QtGui.QApplication.translate("dialog_file", "file", None, QtGui.QApplication.UnicodeUTF8))
self.btnCreate.setText(QtGui.QApplication.translate("dialog_file", "Create", None, QtGui.QApplication.UnicodeUTF8))
class ProgressDialog(QtGui.QDialog):
def __init__(self, parent=None):
QtGui.QDialog.__init__(self, parent = None)
self.ui = Ui_dialog_progress()
self.ui.setupUi(self)
self.setWindowModality(QtCore.Qt.ApplicationModal)
class MyThread(QtCore.QThread):
trigger = QtCore.pyqtSignal()
updatePD = QtCore.pyqtSignal()
def __init__(self, parent=None):
super(MyThread, self).__init__(parent)
def run(self):
self.trigger.emit()
class Main(QtGui.QDialog):
def __init__(self, parent=None):
super(Main, self).__init__(parent)
self.ui = Ui_dialog_file()
self.ui.setupUi(self)
self.ui.btnCreate.clicked.connect(self.start_threads)
def start_threads(self):
self.mythread = MyThread(self)
self.mythread.trigger.connect(self.pdialog)
self.connect(self.mythread, QtCore.SIGNAL("updateFileProgress(int)"), self.updateFileProgress)
self.connect(self.mythread, QtCore.SIGNAL("updateTotalProgress(int)"), self.updateTotalProgress)
self.pd = ProgressDialog()
signal = QtCore.SIGNAL("clicked()")
self.pd.ui.btnPbarCancel.connect(self.pd.ui.btnPbarCancel, signal, self.abort)
self.mythread.start()
def abort(self):
self.pd.close()
self.mythread.terminate()
def updateFileProgress(self, j):
self.pd.ui.pbarFileSize.setValue(j)
print j
def updateTotalProgress(self, i):
self.pd.ui.pbarTotal.setValue(i)
print i
def pdialog(self):
self.pd.show()
i = 1
self.pd.ui.pbarTotal.setValue(0)
self.pd.ui.pbarFileSize.setValue(0)
j = 1
while i < 100:
while j <= 100:
time.sleep(0.01)
self.mythread.emit(QtCore.SIGNAL("updateFileProgress(int)"), j)
QtGui.qApp.processEvents()
j += 1
i += 1
j = 1
self.mythread.emit(QtCore.SIGNAL("updateTotalProgress(int)"), i)
QtGui.qApp.processEvents()
self.pd.close()
if __name__ == '__main__':
app = QtGui.QApplication(sys.argv)
mainwindow = Main()
mainwindow.show()
sys.exit(app.exec_())
1 个回答
2
不要用 terminate()
来结束线程。
可以查看这个链接了解更多信息:http://qt-project.org/doc/qt-4.8/qthread.html#terminate
函数
void QThread::terminate ()
[槽]这个函数会结束线程的执行。线程可能会立刻被结束,也可能不会,这取决于操作系统的调度策略。使用
QThread::wait()
在调用terminate()
后,可以确保线程同步结束。当线程被结束时,所有等待这个线程完成的其他线程都会被唤醒。
警告:这个函数很危险,不建议使用。线程可以在任何时候被结束,这可能会导致线程在修改数据时被强制停止。这样的话,线程就没有机会进行清理,比如解锁任何被占用的资源等。总之,只有在绝对必要的情况下才使用这个函数。
有很多温和的方法可以停止线程。
例如,你可以使用一个标志变量来通知你的工作函数停止。
def start_threads(self):
self.end_flag = False
self.mythread = MyThread(self)
self.mythread.trigger.connect(self.pdialog)
self.connect(self.mythread, QtCore.SIGNAL("updateFileProgress(int)"), self.updateFileProgress)
self.connect(self.mythread, QtCore.SIGNAL("updateTotalProgress(int)"), self.updateTotalProgress)
self.pd = ProgressDialog()
signal = QtCore.SIGNAL("clicked()")
self.pd.ui.btnPbarCancel.connect(self.pd.ui.btnPbarCancel, signal, self.abort)
self.mythread.start()
def abort(self):
self.pd.close()
#self.mythread.terminate()
self.end_flag = True
def pdialog(self):
self.pd.show()
i = 1
self.pd.ui.pbarTotal.setValue(0)
self.pd.ui.pbarFileSize.setValue(0)
j = 1
while i < 100:
while j <= 100:
if self.end_flag:
self.pd.close()
return
time.sleep(0.01)
self.mythread.emit(QtCore.SIGNAL("updateFileProgress(int)"), j)
QtGui.qApp.processEvents()
j += 1
i += 1
j = 1
self.mythread.emit(QtCore.SIGNAL("updateTotalProgress(int)"), i)
QtGui.qApp.processEvents()
self.pd.close()