代码运行但打印出错误:QObject::setParent: Cannot set parent, new parent is in a different thread
。
可能是什么原因?
import Queue, threading
from PyQt4 import QtGui, QtCore
app = QtGui.QApplication([])
class MessageBox(QtGui.QMessageBox):
def __init__(self, parent=None):
QtGui.QMessageBox.__init__(self, parent)
def showMessage(self):
self.setText('Completed')
self.show()
class Thread(QtCore.QThread):
def __init__(self, queue, parent=None):
QtCore.QThread.__init__(self, parent)
self.queue=queue
def run(self):
while True:
number=self.queue.get()
result = self.process(number)
messagebox.showMessage()
self.queue.task_done()
def process(self, number):
timer = QtCore.QTimer()
for i in range(number):
print 'processing: %s'%i
QtCore.QThread.sleep(1)
return True
messagebox = MessageBox()
queue = Queue.Queue()
thread = Thread(queue)
thread.start()
lock=threading.Lock()
lock.acquire()
queue.put(3)
lock.release()
app.exec_()
在下面发布的示例中,我们使用信号和插槽机制(而不是直接从线程调用它)来访问小部件的方法。代码执行按预期工作。即使我知道"解决方案我想知道它为什么会发生。
class Emitter(QtCore.QObject):
signal = QtCore.pyqtSignal()
class MessageBox(QtGui.QMessageBox):
def __init__(self, parent=None):
QtGui.QMessageBox.__init__(self, parent)
def showMessage(self):
self.setText('Completed')
self.show()
class Thread(QtCore.QThread):
def __init__(self, queue, parent=None):
QtCore.QThread.__init__(self, parent)
self.queue=queue
def run(self):
emitter = Emitter()
emitter.signal.connect(messagebox.showMessage)
while True:
number=self.queue.get()
result = self.process(number)
emitter.signal.emit()
self.queue.task_done()
def process(self, number):
timer = QtCore.QTimer()
for i in range(number):
print 'processing: %s'%i
QtCore.QThread.sleep(1)
return True
messagebox = MessageBox()
queue = Queue.Queue()
thread = Thread(queue)
thread.start()
lock=threading.Lock()
lock.acquire()
queue.put(3)
lock.release()
app.exec_()
答案 0 :(得分:2)
你需要做两件事。您需要将发射器对象移动到第二个线程,并且需要将showMessage
声明为插槽。
emitter = Emitter()
emitter.moveToThread(self)
@QtCore.pyqtSlot()
def showMessage(self):
...
但是,最好创建发射器并连接主线程中的信号和插槽,然后将其移动到第二个线程
emitter = Emitter()
emitter.signal.connect(messagebox.showMessage)
emitter.moveToThread(thread)
此外,QThreads
继承自QObject
,因此您不一定需要发射器对象,您可以将信号直接放在QThread上。请注意,QThread
实际上存在于主线程中,并且您在其上的任何插槽(run
除外)将在主线程中执行。
话虽这么说,如果你想在主线程和第二线程之间来回发送数据,你可能想要查看在Qt中使用QThread
的 Worker Pattern