问题是你很困惑QThread
is a Qt线程,即Qt创建的新线程,但是没有,QThread
是一个类handles本机线程,仅run()
方法正在另一个线程上运行,其他方法位于该线程所在的线程中QThread
生活,这是一个QObject
,
QObject 存在于哪个线程中?
线程中的一个QObject
生命是父线程的生命,如果它没有父线程,它将是创建它的线程。另一方面,一个QObject
可以使用移动到另一个线程moveToThread()
,并且它的所有子项也会移动。仅有的moveToThread()
可以使用,如果QObject
没有父母,否则会失败。
使用方法QThread
是创建一个继承自的类QThread
并重写 run 方法并调用start()
以便它开始运行run()
, 在里面run()
方法将完成繁重的任务,但在您的情况下不能使用这种形式,因为任务不会连续执行。比繁重的任务更好的选择是QObject
, 然后QObject
将其移动到另一个线程。
class MainWindow(QMainWindow):
change_text = pyqtSignal(str)
def __init__(self):
super().__init__()
self.button = QPushButton('Push me!', self)
self.setCentralWidget(self.button)
print('main running in:', QThread.currentThread())
# A Worker without a parent is created
# so that it can be moved to another thread.
self.worker = Worker(self.change_text)
thread = QThread(self)
self.worker.moveToThread(thread)
thread.start()
# All methods of self.worker are now executed in another thread.
self.button.clicked.connect(self.worker.do_something_slow)
self.change_text.connect(self.display_changes)
@pyqtSlot(str)
def display_changes( self, text ):
self.button.setText(text)
class Worker(QObject):
def __init__(self, signal_to_emit, parent=None):
super().__init__(parent)
self.signal_to_emit = signal_to_emit
@pyqtSlot()
def do_something_slow( self ):
print('Slot doing stuff in:', QThread.currentThread())
import time
time.sleep(5)
self.signal_to_emit.emit('I did something')
另一方面,没有必要指示连接类型,因为默认情况下它是Qt::AutoConnection
,这种类型的连接在运行时决定是否使用Qt::DirectConnection
如果接收器与发射信号位于同一根电线中,否则,Qt::QueuedConnection
用来。正如您所意识到的,Worker 没有父级,因此要使其具有与类相同的生命周期,它必须是它的一个属性,否则它将是一个被消除的局部变量。另一方面,请注意QThread
接收父级而不是 MainWindow,所以QThread
将驻留在 GUI 线程中,但它处理辅助线程。
有了 Worker 概念,change_text 信号最好不再属于 GUI,而是属于能够更好地解耦对象的 Worker。
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.button = QPushButton('Push me!', self)
self.setCentralWidget(self.button)
print('main running in:', QThread.currentThread())
self.worker = Worker()
thread = QThread(self)
self.worker.moveToThread(thread)
thread.start()
self.button.clicked.connect(self.worker.do_something_slow)
self.worker.change_text.connect(self.display_changes)
@pyqtSlot(str)
def display_changes( self, text ):
self.button.setText(text)
class Worker(QObject):
change_text = pyqtSignal(str)
@pyqtSlot()
def do_something_slow( self ):
print('Slot doing stuff in:', QThread.currentThread())
import time
time.sleep(5)
self.change_text.emit('I did something')