简体   繁体   English

休眠工作线程会导致主GUI冻结

[英]Sleeping the worker thread causes main gui to freeze

Sleeping the worker thread causes main gui to freeze. 休眠工作线程会导致主GUI冻结。

What I want to do is: 我想做的是:

  1. Sleep the worker thread (MyThread)and start the next iteration after some period. 休眠工作线程(MyThread),并在一段时间后开始下一次迭代。
  2. Once MyThread goes into sleep, click on cancel, and cancel the ongoing operation. MyThread进入睡眠状态后,单击“取消”,然后取消正在进行的操作。

In my case the main operation gets canceled when MyThread wakes up again. 就我而言,当MyThread再次唤醒时,主要操作将被取消。 I wanted it to be cancelled immediately. 我希望它立即被取消。

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

Your MyThread doesn't really do anything, as you can see if you look at it's run method. MyThread实际上并没有做任何事情,因为您可以查看它的run方法。 All other methods are still called from the main thread and therefore still happen there. 所有其他方法仍从主线程调用,因此仍在此发生。

Please read Qt Threading Basics , specially the section about QObjects and threads, it should make it clear why the way you're using QThreads is ont working. 请阅读Qt Threading Basics ,特别是有关QObjects和线程的部分,它应该清楚说明为什么您使用QThreads的方式不能正常工作。

What you probably really want to do is: 您可能真正想做的是:

  • make your worker a normal QObject 使您的工作人员成为普通的QObject
  • start a new QThread 开始一个新的QThread
  • move your worker to that thread using the moveToThread method 使用moveToThread方法将您的工作程序移动到该线程
  • interact with it from your main thread using signals 使用信号从主线程与之交互

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM