Multithreading 线程之间未发出PyQt信号
我被卡住了。它应该是容易的,而且我已经使用Qt的C++ API做了很多次,但是由于某些原因,当我在PyQT中这样做时,我的几个信号/时隙中的几个不起作用(我最近从Works:Cords> QObjult在PyQt开始)。我相信它与我向/从中发送信号的独立线程有关Multithreading 线程之间未发出PyQt信号,multithreading,qt,pyqt,signals-slots,worker,Multithreading,Qt,Pyqt,Signals Slots,Worker,我被卡住了。它应该是容易的,而且我已经使用Qt的C++ API做了很多次,但是由于某些原因,当我在PyQT中这样做时,我的几个信号/时隙中的几个不起作用(我最近从Works:Cords> QObjult在PyQt开始)。我相信它与我向/从中发送信号的独立线程有关 from PyQt4.QtCore import QThread, QObject, pyqtSignal, pyqtSlot, QTimer from PyQt4.QtGui import QApplication, QWidget,
from PyQt4.QtCore import QThread, QObject, pyqtSignal, pyqtSlot, QTimer
from PyQt4.QtGui import QApplication, QWidget, QVBoxLayout, QPushButton, QLabel
class Slave(QObject):
countSignal = pyqtSignal(int)
def __init__(self, parent = None):
super(Slave, self).__init__()
self.toggleFlag = False
self.counter = 0
@pyqtSlot()
def work(self):
if not self.toggleFlag: return
if self.counter > 10: self.counter = 0
self.counter += self.counter
self.countSignal.emit(self.counter)
@pyqtSlot()
def toggle(self):
self.toggleFlag = not self.toggleFlag
class Master(QWidget):
toggleSignal = pyqtSignal()
def __init__(self, parent = None):
super(Master, self).__init__()
self.initUi()
self.setupConn()
def __del__(self):
self.thread.quit()
while not self.thread.isFinished(): pass
def initUi(self):
layout = QVBoxLayout()
self.buttonToggleSlave = QPushButton('Start')
self.labelCounterSlave = QLabel('0')
layout.addWidget(self.buttonToggleSlave)
layout.addWidget(self.labelCounterSlave)
self.setLayout(layout)
self.show()
def setupConn(self):
self.thread = QThread()
slave = Slave()
timer = QTimer()
timer.setInterval(100)
# Make sure that both objects are removed properly once the thread is terminated
self.thread.finished.connect(timer.deleteLater)
self.thread.finished.connect(slave.deleteLater)
# Connect the button to the toggle slot of this widget
self.buttonToggleSlave.clicked.connect(self.toggle)
# Connect widget's toggle signal (emitted from inside widget's toggle slot) to slave's toggle slot
self.toggleSignal.connect(slave.toggle)
# Connect timer's timeout signal to slave's work slot
timer.timeout.connect(slave.work)
timer.timeout.connect(self.timeout)
# Connect slave's countSignal signal to widget's viewCounter slot
slave.countSignal.connect(self.viewCounter)
# Start timer
timer.start()
# Move timer and slave to thread
timer.moveToThread(self.thread)
slave.moveToThread(self.thread)
# Start thread
self.thread.start()
@pyqtSlot(int)
def viewCounter(self, value):
print(value)
self.labelCounterSlave.setText(str(value))
@pyqtSlot()
def toggle(self):
print("Toggle called")
self.buttonToggleSlave.setText("Halt" if (self.buttonToggleSlave.text() == "Start") else "Start")
self.toggleSignal.emit()
@pyqtSlot()
def timeout(self):
print("Tick")
if __name__ == "__main__":
app = QApplication([])
w = Master()
w.setStyleSheet('cleanlooks')
app.exec_()
以下内容不会触发/发出:
slot of my widget-我添加了这个,以了解为什么计时器没有触发我的工作线程的slot,但我发现它在这里也不工作timeout()
和work()
我的toggle()
worker类中的插槽Slave
-它从未发出,因为我的小部件的countSignal
插槽从未触发viewCounter()
我在这里遗漏了什么吗?代码中有几个问题妨碍它正常工作
从属对象,并在连接到线程的插槽中调用timer.start()
。不过,在这里您确实需要小心,因为从线程仍将在主线程中运行。或者,您可以将计时器留在主线程中
setupConn()
完成后,slave
和timer
将被垃圾收集。将它们存储为self.slave
和self.timer
。(或者,您应该能够为它们指定一个父对象,但这似乎会导致应用程序在退出时崩溃,所以最好还是将它们存储为实例属性)self.counter+=self.counter
应该是self.counter+=1
?否则计数器永远不会递增:)谢谢我忘了计时器。这是这里的主要问题。对于增量……(FAUPALM)…YEAP,它从不递增:D BTW用于<代码>自己。从< <代码> >代码> >:自拍:<代码> >我也认为它已经超出了范围,但是我习惯了C++版本,在这里,您正在传递一个指针,指向这两个线程,我没有想到这里会改变这个。但我有一个问题——在C++中,如果要把这些东西移到另一个线程,那么创建类成员是不正确的。我想Python不是这样的?这难道不会导致
QObject.deleteLater()
毫无意义吗?@rbaleksandar这可能不是一个好的做法(尽管我不确定替代方案是什么),但在Python中这样做从根本上讲没有什么错。它只是对C++对象的引用。代码> DELTETELATAL()/CUT>仍然有效,如果您尝试通过剩余引用删除QT对象,则会得到一个警告,通知终端正在删除的C++对象。C++中,如果使用类成员,它将(我现在无法正确地记住下面哪一个会发生)要么失败,要么信号处理不当,最终将在错误的线程中发射/捕获。这就是为什么我没有使用<代码>自己/代码>,但是在Python中传递参数的方式与C++中的参数有点不同(就控制是否通过引用或值而言)。如果slave和timer是小部件类的一部分(在我的例子中),那么一旦小部件被销毁,它也应该销毁它的所有成员,包括这两个。HyM.M.RbaleKeStAddioPython,当Python窗口小类被垃圾收集时,Python指针将被删除,但是C++对象本身只会被垃圾收集,如果没有其他引用C++,它们就没有QT相关的父类。我认为只要你把Qt C++对象和Python引用当作只有耦合的,你就能看到什么是有效的,什么是不存在的。就线程中对象的信号连接而言,这可能很有趣:这很有意义。谢谢你的链接页面。现在就看。