我有一个Worker
对象,并使用其方法moveToThread
将其放入一个帖子中。
现在我调用它的work
方法:
示例:
from PySide.QtCore import *
from PySide.QtGui import *
import sys
class Worker(QObject):
def __init__(self):
super().__init__()
def work(self):
print(self.thread().currentThread())
class Example(QWidget):
def __init__(self):
super().__init__()
self.btnInThread = QPushButton('in thread')
self.btnNotInThread = QPushButton('not in thread')
layout = QVBoxLayout()
layout.addWidget(self.btnInThread)
layout.addWidget(self.btnNotInThread)
self.setLayout(layout)
self.worker = Worker()
self.Thread = QThread()
self.worker.moveToThread(self.Thread)
self.Thread.start()
self.btnInThread.clicked.connect(self.worker.work)
self.btnNotInThread.clicked.connect(lambda: self.worker.work())
self.show()
print('{0} <- Main Thread'.format(self.thread().currentThread()))
def main():
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
我做了过多的测试(请参阅代码段中的代码),但我绝对不知道发生了什么。
所以我的问题是:
为什么work
在主线程中执行,而不是在lambda
调用它的对象所在的线程?最重要的是,如果我想调用一个Worker
需要参数的方法,而我无法使用lambda
,我该怎么办?
from PySide.QtCore import *
from PySide.QtGui import *
from time import sleep
import functools
import sys
class Worker(QObject):
def __init__(self):
super().__init__()
def work(self, name='Nothing'):
print('Thread ID: {1} - {0} start'.format(name, QThread.currentThreadId()))
sleep(1)
print('##### End {0}'.format(name))
class HackPushButton(QPushButton):
clicked_with_arg = Signal(str)
def __init__(self, *args):
super().__init__(*args)
self.argument = None
self.clicked.connect(lambda: self.clicked_with_arg.emit(self.argument))
class Example(QWidget):
def __init__(self):
super().__init__()
self.buttonWithoutLambda = QPushButton('[Works] Call work() without arguments and without lambda')
self.buttonWithLambda = QPushButton('[Blocks] Call work() with arguments and with lambda')
self.buttonWithFunctools = QPushButton('[Blocks] Call work() with arguments and with functools')
self.buttonWithHelperFunctionWithArgument = QPushButton('[Blocks] Call work() with arguments and with helper function')
self.buttonWithHelperFunctionWithoutArgument = QPushButton('[Blocks] Call work() without arguments and with helper function')
self.buttonWithHack = HackPushButton('[Works] Call work() with arguments via dirty hack')
layout = QVBoxLayout()
layout.addWidget(self.buttonWithoutLambda)
layout.addWidget(self.buttonWithLambda)
layout.addWidget(self.buttonWithFunctools)
layout.addWidget(self.buttonWithHelperFunctionWithArgument)
layout.addWidget(self.buttonWithHelperFunctionWithoutArgument)
layout.addWidget(self.buttonWithHack)
self.setLayout(layout)
self.Worker = Worker()
self.Thread = QThread()
self.Worker.moveToThread(self.Thread)
self.Thread.start()
# Doesn't block GUI
self.buttonWithoutLambda.clicked.connect(self.Worker.work)
# Blocks GUI
self.buttonWithLambda.clicked.connect(lambda: self.Worker.work('Lambda'))
# Blocks GUI
self.buttonWithFunctools.clicked.connect(functools.partial(self.Worker.work, 'Functools'))
# Blocks GUI
self.helperFunctionArgument = 'Helper function without arguments'
self.buttonWithHelperFunctionWithArgument.clicked.connect(self.helperFunctionWithArgument)
# Blocks GUI
self.buttonWithHelperFunctionWithoutArgument.clicked.connect(self.helperFunctionWithoutArgument)
# Doesn't block GUI
self.buttonWithHack.argument = 'Hack'
self.buttonWithHack.clicked_with_arg.connect(self.Worker.work)
print('Thread ID: {0}'.format(QThread.currentThreadId()))
self.show()
def helperFunctionWithArgument(self):
self.Worker.work(self.helperFunctionArgument)
def helperFunctionWithoutArgument(self):
self.Worker.work()
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
&#13;