2013-05-27 93 views
0

工作者線程睡眠會導致主GUI凍結。工作者線程睡眠會導致主GUI凍結

我想要做的是:

  1. 睡眠輔助線程(MyThread的)和 一段時間後,開始下一次迭代。
  2. 一旦MyThread進入睡眠狀態,點擊取消,並取消正在進行的操作。

在我的情況下,當MyThread再次醒來時,主操作被取消。我希望它立即被取消。

import sys 
from PyQt4 import QtGui, QtCore 
import time 


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() 
    updateFPD = QtCore.pyqtSignal(int, QtCore.QString) 
    updateTPD = QtCore.pyqtSignal(int, QtCore.QString) 
    showpdSignal = QtCore.pyqtSignal(bool) 

    def __init__(self, parent=None, no=0): 
     super(MyThread, self).__init__(parent) 
     self.aborted= False 
     self.threadNo = no 
#  self.name = "Thread %d"%self.threadNo 

    def run(self): 
     self.trigger.emit() 

    def emitSignals(self, iprogress = -99, tprogress = -99,\ 
       updateFPDSignal = True, updateTPDSignal = None,\ 
       showpdSignal = False, peSignal = None, msg = None 
       ): 
     if updateFPDSignal: 
      self.updateFPD.emit(iprogress, msg) 
     if updateTPDSignal: 
      self.updateTPD.emit(tprogress, msg) 
     if showpdSignal: 
      self.showpdSignal.emit(True) 
     else: 
      self.showpdSignal.emit(False) 
     if peSignal: 
      QtGui.QApplication.processEvents() 

    def abort(self): 
     self.aborted = True 
     print "aborted" 

    def stop(self): 
     self.terminate() 

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) 
     self.count = 0 

    def start_threads(self): 
     self.mythread = MyThread() 
     self.pd = ProgressDialog() 
     signal = QtCore.SIGNAL("clicked()") 
     self.pd.ui.btnPbarCancel.connect(self.pd.ui.btnPbarCancel, signal, self.abort) 
     self.mythread.trigger.connect(self.pdialog) 
     self.mythread.updateFPD.connect(self.updateFileProgress) 
     self.mythread.updateTPD.connect(self.updateTotalProgress) 
     self.mythread.start() 

    def abort(self): 
     self.pd.close() 
     self.mythread.aborted = True 

    def updateFileProgress(self, j, name): 
     self.pd.ui.lblFileName.setText(name) 
     self.pd.ui.pbarFileSize.setValue(j) 
     print "name: %s, fileprogress: %d"%(name,j) 

    def updateTotalProgress(self, i, name): 
     self.pd.ui.pbarTotal.setValue(i) 
     print "name: %s, total progress %d"%(name, i) 

    def showProgressDialog(self, show): 
     if show: 
      self.pd.show() 
     else: 
      self.pd.close() 

    def pdialog(self): 
     for k in range(3): 
      self.pd.show() 
      i = 1 
      self.mythread.emitSignals(iprogress =0 , tprogress = 0, updateFPDSignal = True, 
             updateTPDSignal = True, showpdSignal = True, msg = "") 
      j = 1 
      while i < 100: 
       while j <= 100: 
        print j 
        self.mythread.emitSignals(iprogress = j, updateFPDSignal = True,\ 
               peSignal = True, msg = "") 
        j += 1 
       i += 1 
       j = 1 
       self.mythread.emitSignals(tprogress = i, updateTPDSignal = True,\ 
               peSignal = True, msg = "") 
       if self.mythread.aborted: 
        return 
      self.mythread.sleep(10) 
      self.pd.close() 

if __name__ == '__main__': 
    app = QtGui.QApplication(sys.argv) 
    mainwindow = Main() 
    mainwindow.show() 
    sys.exit(app.exec_()) 

回答

0

MyThread並沒有真正做任何事情,因爲你可以看到,如果你看一下它的run方法。所有其他方法仍然從主線程調用,因此仍然發生在那裏。

請仔細閱讀Qt Threading Basics,特別是關於QObject和線程的部分,它應該說明爲什麼您使用QThreads的方式不起作用。

你可能真的想要做的是:

  • 讓你的工人正常的QObject
  • 開始一個新的QThread
  • 移動你的工人線程使用moveToThread方法
  • 互動它從您的主線程使用信號
+0

我經歷了文檔,但不能這樣做。你能相應地重新編排代碼並幫助我嗎? –

+0

我可以在這裏得到一些幫助嗎? –