我正在写一个加密图像的应用程序。主要问题是我想添加到我的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函数之一发出的信号。
提前感谢任何我犯了错误或我应该做什么的建议。
答案 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_())