如何从 QThread 调用小部件的方法
How to call widget's method from QThread
代码运行但打印出错误: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_()
在下面发布的示例中,我们使用信号和槽机制(而不是直接从线程调用它)到达小部件的方法。代码执行按预期工作。即使在我 "know" 解决方案时,我也想知道它为什么会发生。
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_()
你需要做两件事。需要将发射器对象移动到第二个线程,需要声明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
除外)都将在主线程中执行。
话虽如此,如果您想在主线程和第二线程之间来回发送数据,您可能需要查看使用 [=16= 的 Worker Pattern ] 在 Qt 中。
代码运行但打印出错误: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_()
在下面发布的示例中,我们使用信号和槽机制(而不是直接从线程调用它)到达小部件的方法。代码执行按预期工作。即使在我 "know" 解决方案时,我也想知道它为什么会发生。
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_()
你需要做两件事。需要将发射器对象移动到第二个线程,需要声明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
除外)都将在主线程中执行。
话虽如此,如果您想在主线程和第二线程之间来回发送数据,您可能需要查看使用 [=16= 的 Worker Pattern ] 在 Qt 中。