2013-02-24 131 views
1

以下代碼的問題是工作線程在按下取消按鈕後未終止,並且def pdialog(self)不會在while循環結束之前停止。我想停止進度條打印進度以及後臺進程。發送終止後Qthread不停止

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_()) 

回答

2

請勿使用terminate()來終止線程。

參見http://qt-project.org/doc/qt-4.8/qthread.html#terminate

空隙的QThread ::終止()[時隙]

終止線程的執行。該線程可能會或可能不會立即終止,具體取決於操作系統調度策略。在terminate()之後使用QThread :: wait()進行同步終止。

當線程終止時,等待線程完成的所有線程都將被喚醒。

警告:此功能是危險的,它的使用是不鼓勵的。該線程可以在其代碼路徑中的任何點終止。線程可以在修改數據時被終止。線程無法自行清理,解鎖任何持有的互斥鎖等。簡而言之,只有在絕對必要時才使用此函數。

有很多溫柔的方法來阻止線程。
例如,您可以使用標誌變量來通知您的工作人員功能停止。

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() 
+0

謝謝nymk。解決了這個問題 – 2013-02-25 13:37:18