我有以下代码执行后台操作( scan_value
同时更新在用户界面(进度条) progress
)。 scan_value
超过在一些值迭代obj
,发射的信号( value_changed
)每个的值改变的时间。 对于不是与此有关的原因,我有一个对象(包装这种Scanner
在另一个线程)。 该按钮时,扫描仪被称为scan
被clicked
。 在这里,我的问题是...下面的代码工作正常(即都会更新进度条上的时间)。
# I am copying only the relevant code here.
def update_progress_bar(new, old):
fraction = (new - start) / (stop - start)
progress.setValue(fraction * 100)
obj.value_changed.connect(update_progress_bar)
class Scanner(QObject):
def scan(self):
scan_value(start, stop, step)
progress.setValue(100)
thread = QThread()
scanner = Scanner()
scanner.moveToThread(thread)
thread.start()
scan.clicked.connect(scanner.scan)
但是,如果我的最后部分改成这样:
thread = QThread()
scanner = Scanner()
scan.clicked.connect(scanner.scan) # This was at the end!
scanner.moveToThread(thread)
thread.start()
进度条被仅在结束时更新(我的猜测是,一切都在同一线程上运行)。 如果我移动对象接收对象到线程之后的信号的前连接到一个时隙它应该是不相关的。
它不应该的问题的连接是否之前或工人对象移动到另一个线程后作出的。 从引用的Qt文档 :
Qt的::自动连接 -如果该信号是从一个不同的线程比接收对象发射,该信号被排队时,表现为QT :: QueuedConnection。 否则,该插槽直接调用,表现为Qt的:: DirectConnection。 当信号被发射时,确定类型的连接 。 [强调]
所以,只要type
的参数connect
被设置为QtCore.Qt.AutoConnection
(这是默认值),Qt的应确保信号在恰当的方式发出的。
与示例代码的问题是更可能是与槽比信号 。 该信号是连接蟒方法可能需要被标记为一个Qt槽,使用pyqtSlot装饰 :
from QtCore import pyqtSlot
class Scanner(QObject):
@pyqtSlot()
def scan(self):
scan_value(start, stop, step)
progress.setValue(100)
编辑 :
应该澄清,这只是在当信号被发射的连接类型确定的Qt相当新的版本。 引入这种行为(以及Qt中的多线程支持其他多项变更)4.4版本。
此外,它可能是值得的具体PyQt的,问题进一步扩大。 在PyQt的,信号可以连接到一个Qt槽,另一个信号,或可调用任何蟒。 对于后一种情况,在内部创建一个代理对象,它包装在可调用蟒和提供由Qt的信号/槽机构所需的槽。
正是这种代理对象,这是问题的原因。 一旦代理被创建,PyQt的将只是这样做:
if (rx_qobj)
proxy->moveToThread(rx_qobj->thread());
如果之后接收对象已经被移动到它的螺纹是由连接其是细; 但如果它之前提出的,该代理将留在主线程。
使用@pyqtSlot
装饰完全避免这个问题,因为它更直接地创建一个Qt槽,不使用代理对象都没有。
最后,还应该指出的是,这个问题不会影响当前PySide。
我的问题是由movinf的地方,因为我访问只有我的工人对象类,这是在另一个线程的实例化之后存在的对象的工作线程被初始化,在我的情况下,现货连接解决。
在之后的信号简单地连接self.createWorkerThread()
问候
这与连接类型的Qt做。
http://pyqt.sourceforge.net/Docs/PyQt5/signals_slots.html#connect
http://qt-project.org/doc/qt-4.8/qt.html#ConnectionType-enum
如果两个对象住在同一线程中,一个标准的连接类型制成,这导致在一个普通的函数调用。 在这种情况下,耗时的操作发生在GUI线程,和接口块。
如果连接类型是消息传递风格连接,该信号被使用在其他的线程来处理一个消息发射。 GUI线程现在可以自由地更新用户界面。
当你不指定在连接功能的连接类型,类型自动检测。