如何从PyQt GUI中断QThread?

时间:2014-09-07 12:33:18

标签: user-interface pyqt4 qthread

我正在写一个加密图像的应用程序。主要问题是我想添加到我的GUI选项,只需单击一个gui按钮即可中断(甚至终止)加密线程(当它工作时)。 Gui和算法工作正常(ia也提供gui的进度条连接)但是当线程开始生成时我无法点击gui上的任何内容(甚至是终止按钮)。如果在线程中发生错误并且gui仍然正常工作,那么按钮正确连接,我可以单击按钮并终止该过程。 我认为gui冻结了,因为线程是在gui函数中定义的,所以我把它从gui移到了主程序函数中。 我想指出我没有创建rad子类(正如Maya Posch建议http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

这是主要功能的代码:

def main():
   app = QApplication(sys.argv)
   cryptoThread = QtCore.QThread()
   prog = ProgramWindow()
   worker = ic.imageCryptographer()
   worker.moveToThread(cryptoThread)

   prog.progressButton.clicked.connect(lambda: prog.interruptEncrypting(cryptoThread))
   prog.startEncrypting.connect(cryptoThread.start)
   worker.encryptSignal.connect(prog.progressbar.setValue)
   worker.done.connect(lambda: prog.endEncrypting(cryptoThread, worker))
   cryptoThread.started.connect(lambda: worker.compute(prog.shareFlag, prog.binMatrix))

   sys.exit(app.exec_())

类ProgramWindow中的函数:

def interruptEncrypting(self, thread):
    thread.terminate()
    thread.wait()
    self.interrupt()
    return

def endEncrypting(self, thread, worker):
    self.keys = worker.keys
    thread.quit()
    self.progressbarWidget.setVisible(False)
    self.saveOption.setEnabled(True)
    self.cryptoWorkdeskOption.setEnabled(True)
    self.openCryptoWorkdesk()

def interrupt(self):
    self.progressbarWidget.setVisible(False)
    if self.state==1:
        self.buttonSwapWidget.setVisible(True)
    elif self.state==2:
        self.keyChooseWidget.setVisible(True)

变量:shareFlag和binMatrix与线程通信无关(它们是变量necceseray以计算工作方法.StartEncrypting是从ProgramWindow函数之一发出的信号。

提前感谢任何我犯了错误或我应该做什么的建议。

1 个答案:

答案 0 :(得分:1)

是的,只是尝试过,可以确认我在评论中已经指出的内容。虽然您在连接worker时将cryptoThread移动到cryptoThread.started.connect(lambda: worker.compute(prog.shareFlag, prog.binMatrix))(及其所有方法),但您创建了一个新的lambda对象,该对象未在cryptoThread内运行但在主要内部线。这就是为什么它不会在你的主应用程序之外运行的原因。您必须连接cryptoThread.started.connect(worker.compute)并在一些额外的初始化/配置方法中传递参数。

我用以下代码测试了它:

import sys
import time
from PyQt4 import QtGui, QtCore

class Worker(QtCore.QObject):
    def __init__(self, parent=None):
        QtCore.QObject.__init__(self, parent)

        self.t1 = QtCore.QThread()
        self.moveToThread(self.t1)
        self.t1.start()

    def do_stuff(self):
        while True:
            print 'loop'
            time.sleep(1)

class MainWindow(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)

        self.worker = Worker()

        self.button = QtGui.QPushButton('start', self)
        self.button.clicked.connect(self.worker.do_stuff)  # connect directly with worker's method do_stuff
        #self.button.clicked.connect(lambda: self.worker.do_stuff())  # connect with lambda object containing do_stuff

app = QtGui.QApplication(sys.argv)
main = MainWindow()
main.show()
sys.exit(app.exec_())