0

休眠工作线程会导致主 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_())
4

1 回答 1

0

MyThread并没有真正做任何事情,你可以看看它的run方法。所有其他方法仍然从主线程调用,因此仍然在那里发生。

请阅读Qt Threading Basics,特别是关于 QObjects 和线程的部分,它应该清楚为什么您使用 QThreads 的方式不起作用。

您可能真正想做的是:

  • 让你的工人成为一个普通的 QObject
  • 开始一个新的 QThread
  • moveToThread使用该方法将您的工作人员移动到该线程
  • 使用信号从主线程与其交互
于 2013-05-27T11:21:31.783 回答